Сокращение для числа тегов, имеющих более длинный [и почти такой же] Xpath - PullRequest
3 голосов
/ 25 марта 2010

Например: это xslt

<xsl:template match="/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node_1
|/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node_2
|/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node_3
 .
 .
|/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node_N"/>

В приведенном выше коде я могу использовать XPath /root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4 только один раз [использовать фигурные скобки или что-то еще] и уменьшить объем кода?

Как видите, все узлы являются братьями и сестрами друг друга, поэтому, кроме их имени, их Xpath одинаков. Есть ли свойство короткой руки?

XSLT 1.0 (или Xpath1.0) позволяет это делать?

Ответы [ 3 ]

3 голосов
/ 25 марта 2010

Спросите себя, действительно ли необходимо длинное конкретное выражение соответствия. Я вижу, что это только пример, но вам не обязательно включать полный путь к элементу, только столько, сколько необходимо, чтобы сделать его однозначным.

Далее я напоминаю вам о оси self:

<xsl:template match="/.../dummy4/*[self::node_1 or self::node_2 ...]" />

Если имя структурировано и предсказуемо, вы можете сделать

<xsl:template match="/.../dummy4/*[substring-before(name(), '_') = 'node']" />
2 голосов
/ 25 марта 2010

XSLT 1.0 (или Xpath1.0) это позволяет?

Ниже приведено правильное выражение XPath 1.0 :

root/sub-root/parent/child/grand_child
              /dummy1/dummy2/dummy3/dummy4
                /*
                 [starts-with(name(), 'node_')
                and
                  substring-after(name(), 'node_') >= 1
                and
                  not(substring-after(name(), 'node_') > $N)
                  ]

Однако шаблоны соответствия являются лишь подмножеством всех выражений XPath , и к ним применяются определенные ограничения. В частности, в XSLT 1.0 они не могут содержать ссылку на xsl: variable .

В случае, если значение N статически известно, тогда подставляется это буквальное значение (скажем, 1000) в приведенном выше выражении XPath, и, таким образом, у него будет действительный шаблон соответствия XSLT 1.0.

Обратите внимание, что это крайний случай , и крайне маловероятно, что при любых практических обстоятельствах потребуется такой длинный шаблон сопоставления. По определению шаблон сопоставления не должен указывать полный путь к узлу - только достаточный «from-right-subpath», который устраняет неоднозначность узла с другими узлами с тем же именем, которые должны обрабатываться другим шаблоном.

Таким образом, в большинстве случаев будет достаточно даже :

 *
 [starts-with(name(), 'node_')
and
  substring-after(name(), 'node_') >= 1
and
   not(substring-after(name(), 'node_') > {N})

 ]

где {N} должен быть заменен целочисленным литералом - фактическое значение $ N.

Или, в самом простом случае (случается довольно часто), если есть четыре узла и нет необходимости в устранении неоднозначности , нужно просто использовать:

 node_1|node_2|node_3|node_4
1 голос
/ 25 марта 2010

Проверено только в онлайн-инструменте xpath, поэтому не совсем уверен, но оно должно работать

<xsl:template match="/root/sub-root/parent/child/grand_child/dummy1/dummy2/dummy3/dummy4/node()[name() = 'node_1' or name()='node_2' ... or name()='node_N']"/>

Если в dummy4 нет узлов, которые вы хотите опустить, просто отбросьте [..]

...