Следствие xsl: value-of как потомка xsl: variable - PullRequest
2 голосов
/ 26 апреля 2011

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

<xsl:variable name="hello" select="$world" />

<xsl:variable name="hello">
    <xsl:value-of select="$world" />
</xsl:variable>

<xsl:variable name="hello">
    <xsl:choose>
        <xsl:when test="$something=true()">
            <xsl:value-of select="$world" />
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$world" />
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

Редактировать 1: Я хочу обработать $hello в <xsl:for-each select="$hello">.С третьим блоком выше у <xsl:for-each> есть только один элемент для обработки, который содержит объединенное содержимое $world.Почему это так?

Ответы [ 3 ]

2 голосов
/ 26 апреля 2011

Первый xsl:variable будет иметь то же значение и тип, что и $world.Вторым является фрагмент дерева результатов с единственным текстовым узлом со строковым значением $world.Третий также является фрагментом дерева результатов с одним текстовым узлом.

Я полагаю, вы хотите либо

  <xsl:variable name="hello" select="if (condition) then $world else $foo"/>

в XSLT 2.0, и тогда ваш for-each select="$hello" будет работать так, как вы хотите, или вXSLT 1.0 плюс EXSLT общий вы хотите

<xsl:variable name="hello">
  <xsl:choose>
    <xsl:when test="condition">
      <xsl:copy-of select="$world"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy-of select="$foo"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>

<xsl:for-each select="exsl:node-set($hello)/*">...</xsl:for-each>
1 голос
/ 27 апреля 2011

Хотя все три примера действительны как в XSLT 1.0, так и в XSLT 2.0, способ описания семантики в этих двух спецификациях сильно отличается; также, когда $ value содержит несколько узлов, эффект <xsl:value-of select="$value"/> зависит от того, указывает ли таблица стилей version = "1.0" или version = "2.0".

Основные вещи, которые следует запомнить, которые применимы к обеим версиям, это: (a) xsl: value-of создает текстовый узел путем преобразования всего, что он выбирает, в строку, и (b) xsl: переменная с содержащимися в ней инструкциями (и без «as») создает новое дерево с корнем в узле документа.

0 голосов
/ 27 апреля 2011
  <xsl:variable name="hello">
      <xsl:choose>
          <xsl:when test="$something=true()">
              <xsl:value-of select="$world" />
          </xsl:when>
          <xsl:otherwise>
              <xsl:value-of select="$world" />
          </xsl:otherwise>            
         </xsl:choose>        
    </xsl:variable>

Я хочу обработать $hello в <xsl:for-each select="$hello">.С блоком выше у <xsl:for-each> есть только один элемент для обработки, который содержит объединенное содержимое $world.Почему это так?

Переменная с именем $hello содержит строковое значение $world.Это по определению, как <xsl:value-of> ведет себя в XSLT 1.0.

Вы не показали нам, как определяется $world, но если он содержит один элемент или целое дерево документов, то (снова)определение, его строковое значение - это объединение (в порядке документа) всех его потомков - текстовых узлов.

Это именно то, что вы видите.

Ситуация будет другойесли от :

<xsl:value-of select="$world" />

вы используете :

<xsl:copy-of select="$world" />

Это копирует все поддерево, корнем которого является элемент (или корневой узел * 1030).* в случае, когда $world содержит полный документ), содержащийся в $world.

Однако в XSLT 1.0 это создает так называемый RTF (Result Tree Fragment) и по определению нельзя использовать RTF какшаг местоположения в выражении XPath (1.0).

Сначала необходимо преобразовать его в обычное дерево (узел документа), используя предоставляемую поставщиком функцию расширения, которая чаще всего имеет локальное имя node-set, но находится вспецифичное для поставщика пространство имен.

Типичным примером является :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vWorld" select="/*"/>

 <xsl:template match="/">
  <xsl:variable name="vrtfHello">
    <xsl:copy-of select="$vWorld"/>
  </xsl:variable>

  <xsl:variable name="vHello" select=
   "ext:node-set($vrtfHello)/*"/>

  <xsl:copy-of select="$vHello/*[3]"/>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к следующему документу XML:

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

результат равен (как и ожидалось):

<num>03</num>

Здесь мы используем функцию расширения ext:node-set() в пространстве имен "http://exslt.org/common", как указано в независимой от производителя библиотеке EXSLT.Большинство процессоров XSLT 1.0 поддерживают EXSLT, и использование его функции расширения node-set() не уменьшает степень переносимости приложения XSLT на все такие процессоры XSLT.

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