xsl:элемент xsl: функция = странность? (Saxon, Java)

#xslt #xpath #xslt-2.0

#xslt #xpath #xslt-2.0

Вопрос:

Я уже несколько часов бьюсь над этим кодом XSL (Saxon / Java) и все еще не могу в нем разобраться. Я сузил проблему до этого фрагмента:

 <xsl:function name="my:fff" >
  <xsl:element name="p0">
    <p1 aaa='AAA' />
  </xsl:element>
</xsl:function>

<xsl:function name="my:ggg">

  <xsl:variable name="v" select="my:fff()" />

  <!-- Debug messages -->
  <xsl:message>
    $v          '<xsl:sequence select="$v" />'
    $v/*        '<xsl:sequence select="$v/*" />'
    $v/*/@aaa   '<xsl:value-of select="$v/*/@aaa" />'
    $v/p0       '<xsl:sequence select="$v/p0" />'
  </xsl:message>
    ...
</xsl:function>
  

Вывод, выводимый in my:ggg , выглядит следующим образом:

   $v          '<p0><p1 aaa="AAA"/></p0>'
  $v/*        '<p1 aaa="AAA"/>'
  $v/*/@aaa   'AAA'
  $v/p0       ''
  

Первые три строки в порядке. Но четвертая строка, которая выводит пустую строку, странная. Я имею в виду, если $v есть <p0><p1 aaa="AAA"/></po> (как указано в первой строке), то почему этого $v/p0 нет <p1 aaa="AAA"/> ?

Чего я не понимаю?

Комментарии:

1. $v элемент, возвращаемый с помощью my:fff , поэтому он является тегом <p0> , включающим дочерние элементы. $v/p0 пытается выбрать a <p0> в качестве дочернего тега в $v , который пуст, поскольку тег, <p0> выбранный $v , не содержит a <p0> .

2. @rsp — Вы должны сделать это ответом, так как это и есть на самом деле ответ.

Ответ №1:

Ваши рассуждения были бы в порядке, если бы my:fff() функция возвращала узел документа, а не элемент ( p0 который сам по себе не имеет p0 дочернего элемента).

Итак, если вы измените функцию на следующую:

  <xsl:function name="my:fff" as="document-node()" >
        <xsl:document>
         <xsl:element name="p0">
            <p1 aaa='AAA' />
         </xsl:element>
        </xsl:document>
 </xsl:function>
  

И полное преобразование было бы:

 <xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:sequence select="my:ggg()"/>
 </xsl:template>

 <xsl:function name="my:fff" as="document-node()" >
        <xsl:document>
         <xsl:element name="p0">
            <p1 aaa='AAA' />
         </xsl:element>
        </xsl:document>
 </xsl:function>

 <xsl:function name="my:ggg">
    <xsl:variable name="v" select="my:fff()" />
    <!-- Debug messages -->
    <xsl:message>
         $v          '
        <xsl:sequence select="$v" />
        '     $v/*        '
        <xsl:sequence select="$v/*" />
        '     $v/*/@aaa   '
        <xsl:value-of select="$v/*/@aaa" />
        '     $v/p0       '
        <xsl:sequence select="$v/p0" />'
    </xsl:message>     ...
 </xsl:function>
</xsl:stylesheet>
  

затем, применяя это преобразование к любому XML-документу (не используется), теперь получается следующий отладочный вывод:

      $v          '<p0><p1 xmlns:my="my:my" aaa="AAA"/></p0>'
     $v/*        '<p0><p1 xmlns:my="my:my" aaa="AAA"/></p0>'
     $v/*/@aaa   ''
     $v/p0       '<p0><p1 xmlns:my="my:my" aaa="AAA"/></p0>'
  

вероятно, это то, что вы хотите, за исключением aaa атрибута, к которому необходимо обращаться как: $v/*/*/@aaa

Ответ №2:

$v элемент, возвращаемый с помощью my:fff , поэтому он является тегом <p0> , включающим дочерние элементы. $v/p0 пытается выбрать a <p0> в качестве дочернего тега в $v , который пуст, поскольку тег, <p0> выбранный $v , не содержит a <p0> .

Ответ №3:

Вам было бы легче диагностировать такого рода проблемы, если бы вы взяли за привычку всегда объявлять типы аргументов и возвращаемых значений функции. Это заставило бы вас задуматься о том, что возвращает my:fff. В данном случае это элемент node (без родительских элементов): вы можете объявить результат как as="element(p0)" . Тогда было бы гораздо очевиднее, что элемент p0 вряд ли будет иметь дочерних элементов p0, так что my:fff()/p0 , вероятно, это неправильно.