Можно ли динамически построить этот запрос XPath в XSLT? - PullRequest
6 голосов
/ 21 марта 2010

У меня есть документ, похожий на

<root>
    <element>
        <subelement1 />
        <subelement2 />
    </element>
    <element>
        <subelement2 />
        <subelement1 />
    </element>
</root>

В моем листе XSLT в контексте /element[2]/[someNode] я хочу получить число, представляющее расстояние /element[1]/[someNode] (т. Е. Количество предшествующих братьев и сестер /element1/[someNode]). Например, в контексте /element[2]/subelement1 я бы хотел получить какой-нибудь способ получить число 2, расстояние от /element[1] до /element[1]/subelement2. Мне только когда-либо нужно расстояние данного имени узла от первого экземпляра <element>.

Интуитивно я думал, что мог бы построить это как

 <xsl:variable name="nodename" select="name()" />
 <xsl:value-of select="/element[1]/$nodename/preceding-sibling::*" />

но, к сожалению, этот лист не компилируется. Возможно ли то, что я пытаюсь достичь в XSLT?

Ответы [ 3 ]

8 голосов
/ 21 марта 2010
  1. Нельзя использовать переменную XSLT в качестве оси оператора XPATH, но вы можете использовать ее в фильтре предикатов. Таким образом, если вы хотите сопоставить какой-либо элемент (например, *), а затем ограничить его элементами, имя () которых равно значению, хранящемуся в вашей переменной (например, *[name()=$nodename]), XPATH будет действительным.

  2. XPATH, который вы строили, вернул бы значение соответствующего элемента. Если вы хотите вернуть количество элементов, соответствующих этому шаблону, вы можете использовать функцию count().

  3. В вашем примере XML есть элемент документа <root>, но ваш XPATH не включает <root>.

Возвращает количество предшествующих элементов, используя переменную, назначенную узлом контекста:

<xsl:variable name="nodename" select="name()" />
<xsl:value-of select="count(/root/element[1]/*[name()=$nodename]/preceding-sibling::*)" />

Вы можете исключить переменную и просто использовать:

<xsl:value-of select="count(/root/element[1]/*[name()=name(current())]/preceding-sibling::*)" />
1 голос
/ 21 марта 2010

*[name() = $nodename] может быть тем, что вы хотите вместо $nodename, но тогда вам лучше определить две переменные со значением local-name () и namespace-uri () и проверить, например, *[local-name() = $localname and namespace-uri() = $namespaceuri] для безопасного выбора имён в пространстве имен.

0 голосов
/ 21 марта 2010

Создание xpath'а, к сожалению, невозможно. XPath статически компилируются; вы не можете генерировать их на лету (или если вы это делаете, они просто строки и не могут быть выполнены).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...