Использование xsl: variable в операторе select xsl: foreach - PullRequest
3 голосов
/ 15 марта 2010

Я пытаюсь перебрать документ xml, используя xsl: foreach, но мне нужно, чтобы select = "" был динамическим, поэтому я использую переменную в качестве источника. Вот что я попробовал:

...

<xsl:template name="SetDataPath">
  <xsl:param name="Type" />

  <xsl:variable name="Path_1">/Rating/Path1/*</xsl:variable>
  <xsl:variable name="Path_2">/Rating/Path2/*</xsl:variable>

  <xsl:if test="$Type='1'">
    <xsl:value-of select="$Path_1"/>
  </xsl:if>

  <xsl:if test="$Type='2'">
    <xsl:value-of select="$Path_2"/>
  </xsl:if>
<xsl:template>

...

    <!-- Set Data Path according to Type -->
  <xsl:variable name="DataPath">
    <xsl:call-template name="SetDataPath">
      <xsl:with-param name="Type" select="/Rating/Type" />
    </xsl:call-template> 
  </xsl:variable>

...

<xsl:for-each select="$DataPath">

...

В foreach возникла ошибка: «XslTransformException - чтобы использовать фрагмент результирующего дерева в выражении пути, сначала преобразуйте его в набор узлов, используя функцию msxsl: node-set ().»

Когда я использую функцию msxsl: node-set (), мои результаты остаются пустыми.

Я знаю, что я устанавливаю $ DataPath в строку, но разве функция node-set () не должна создавать из нее набор узлов? Я что-то пропустил? Когда я не использую переменную:

<xsl:for-each select="/Rating/Path1/*">

Я получаю правильные результаты.

Вот файл данных XML, который я использую:

<Rating>
    <Type>1</Type>
    <Path1>
       <sarah>
          <dob>1-3-86</dob>
          <user>Sarah</user>
       </sarah>
       <joe>
          <dob>11-12-85</dob>
          <user>Joe</user>
       </joe>
    </Path1>
    <Path2>
       <jeff>
          <dob>11-3-84</dob>
          <user>Jeff</user>
       </jeff>
       <shawn>
          <dob>3-5-81</dob>
          <user>Shawn</user>
       </shawn>
    </Path2>
</Rating>

У меня простой вопрос, как вы запускаете foreach по двум разным путям?

Ответы [ 3 ]

3 голосов
/ 16 марта 2010

Попробуйте это:

   <xsl:for-each select="/Rating[Type='1']/Path1/*
                         |
                          /Rating[Type='2']/Path2/*">
3 голосов
/ 16 марта 2010

Стандартный XSLT 1.0 не поддерживает динамическую оценку xpath. Однако вы можете достичь желаемого результата, реструктурировав свое решение для вызова именованного шаблона, передав в качестве параметра набор узлов, который вы хотите обработать:

<xsl:variable name="Type" select="/Rating/Type"/>
<xsl:choose>
    <xsl:when test="$Type='1'">
        <xsl:call-template name="DoStuff">
            <xsl:with-param name="Input" select="/Rating/Path1/*"/>
        </xsl:call-template>
    </xsl:when>
    <xsl:when test="$Type='2'">
        <xsl:call-template name="DoStuff">
            <xsl:with-param name="Input" select="/Rating/Path2/*"/>
        </xsl:call-template>
    </xsl:when>
</xsl:choose>

...

<xsl:template name="DoStuff">
    <xsl:param name="Input"/>
    <xsl:for-each select="$Input">
        <!-- Do stuff with input -->
    </xsl:for-each>
</xsl:template>
0 голосов
/ 15 марта 2010

Упомянутая вами функция node-set() может преобразовывать фрагменты дерева результатов в наборы узлов, это правильно. Но: Ваш XSLT не создает фрагмент дерева результатов.

Ваш шаблон SetDataPath создает строку, которая затем сохраняется в вашей переменной $DataPath. Когда вы делаете <xsl:for-each select="$DataPath">, процессор XSLT подавляется тем фактом, что DataPath содержит не набор узлов, а строку.

Кажется, что вся ваша таблица стилей вращается вокруг идеи динамического выбора / оценки выражений XPath. Отбросьте эту мысль, это ни невозможно, ни необходимо.

Покажите ваш ввод XML и укажите преобразование, которое вы хотите сделать, и я могу попытаться показать вам способ сделать это.

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