Почему я не могу использовать значения узлов, которые я получаю с помощью exsl: node-set / set: different в XPath-Expression? - PullRequest
1 голос
/ 26 августа 2010

В таблице стилей xslt я использую методы exsl:node-set и set:distinct для доступа и фильтрации уникальных узлов из переменной, которая содержит фрагмент дерева результатов.Я могу записать значения этих узлов в мой выходной файл, например:

<xsl:variable name="myNodes">
  <xsl:call-template name="getNodes"/>
</xsl:variable>

<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
  <xsl:value-of select="."/>
</xsl:for-each>

Значения ключей записываются в вывод, как и ожидалось.Однако, если я попытаюсь использовать значения в выражении XPath, произойдет сбой:

<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
  <xsl:variable name="result" select="/tree//somenode[@key = current()]"/>
  <xsl:value-of select="$result"/>
</xsl:for-each>

Теперь вывод пуст, тогда как я знаю, что в моем input-xml есть «somenode», который долженбыть выбранным выражением XPath и его значение не пустое.

Теперь мой вопрос: почему это происходит?

Я использую Java 1.6, Xerces 2.7 и Xalan 2.7.

обновление: по запросу, некоторые данные для примера: XML-документ содержит:

<tree>
  <somenode key="123"/>
  <num>123</num>
  <num>0815</num>
</tree>

шаблон getNodes:

<xsl:template name="getNodes">
  <xsl:for-each select="/tree/num">
    <xsl:element name="key">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:for-each>
</xsl:template>

Ответы [ 2 ]

3 голосов
/ 26 августа 2010

Вот преобразование, которое делает что-то близкое к тому, что вы хотите :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:set="http://exslt.org/sets"
 xmlns:exsl="http://exslt.org/common"
 >
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:template match="/">
  <xsl:variable name="myNodes">
    <xsl:call-template name="getNodes"/>
  </xsl:variable>


  <xsl:variable name="vDoc" select="/"/>

  <xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
    <xsl:variable name="result" select="$vDoc/tree//somenode[@key = current()]"/>
    <xsl:copy-of select="$result"/>
  </xsl:for-each>
 </xsl:template>

 <xsl:template name="getNodes">
  <xsl:for-each select="/tree/num">
    <xsl:element name="key">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<tree>
  <somenode key="123"/>
  <num>123</num>
  <num>0815</num>
</tree>

желаемый результат получен :

<somenode key="123"/>

Do note :

  1. К исходному XML-документу нельзя напрямую получить доступ внутри <xsl:for-each>, , поскольку эта инструкция устанавливает текущий узел на узел в другом документе - временное дерево, созданное exsl:node-set().

  2. По этой причине мы фиксируем исходный XML-документ в переменной $vDoc. Мы получаем доступ к исходному XML-документу внутри <xsl:for-each> через эту переменную.

  3. Элемент <somenode key="123"/> не имеет потомков текстовых узлов и, следовательно, не имеет строкового значения .Использование <xsl:value-of> не приведет к выводу.Вот почему мы используем <xsl:copy-of> здесь - он копирует весь элемент, и мы видим результат.

0 голосов
/ 26 августа 2010

Эта таблица стилей делает то же самое, что и вы, без расширений:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="NumByValue" match="num" use="."/>
    <xsl:template match="num[count(.|key('NumByValue',.)[1])=1]">
        <xsl:copy-of select="../somenode[@key=current()]"/>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<somenode key="123" />
...