2010-03-25 2 views
3

Например: это XSLTКороткие руки для ряда тегов, имеющих более длительную [и почти такой же] Xpath

<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)?

+0

Хороший вопрос снова, @infant программист (+1). Вам редко приходится указывать в шаблоне соответствия полный путь к узлу - см. Мой ответ. –

ответ

1

только протестировали его в онлайн-инструмент 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 вы хотите пропустить, просто перенесите [..]

3

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

Кроме того, я хотел бы напомнить вам о self оси:

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

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

<xsl:template match="/.../dummy4/*[substring-before(name(), '_') = 'node']" /> 
2

Does 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) 
        ] 

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

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

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

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

* 
[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 
+0

Что делать, если имена узлов не идентичны? Я имею в виду node_1, node_2 - это просто примеры .. в типичном примере у меня их не будет. –

+0

@ infant-programmer, тогда вам нужно иметь все имена возможных элементов в отдельной структуре и сравнить имя eac элемент обрабатывается с именами из этой структуры. Говоря об этом, мы говорим о наличии отдельного «файла поиска». Это становится другим вопросом, вы можете спросить об этом. :) –

+0

Нет, спасибо, я думаю, что мне это никогда не понадобится, предложение Ледхунда полностью соответствует моей необходимости, и вы тоже многое разъяснили :) спасибо :) –