Шаблоны XSLT и рекурсия

Я плохо знаком с XSLT и имею некоторые проблемы при попытке отформатировать XML-документ, который имеет рекурсивные узлы.

Мой код XML:

Надо надеяться, мои шоу XML:

  • Все <item> вкладываются с <items>
  • Объект может иметь или просто атрибуты или подузлы
  • Уровень, к который <item> узлы вкладываются, может быть infinently глубоко
<?xml version="1.0" encoding="utf-8" ?> 
- <items>
  <item groupID="1" name="Home" url="//" /> 
- <item groupID="2" name="Guides" url="/Guides/">
- <items>
- <item groupID="26" name="Online-Poker-Guide" url="/Guides/Online-Poker-Guide/">
- <items>
- <item>
  <id>107</id> 
- <title>
- <![CDATA[ Poker Betting - Online Poker Betting Structures
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/online-poker-betting-structures
  ]]> 
  </url>
  </item>
- <item>
  <id>114</id> 
- <title>
- <![CDATA[ Beginners&#39; Poker - Poker Hand Ranking
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/online-poker-hand-ranking
  ]]> 
  </url>
  </item>
- <item>
  <id>115</id> 
- <title>
- <![CDATA[ Poker Terms - 4th Street and 5th Street
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/online-poker-poker-terms
  ]]> 
  </url>
  </item>
- <item>
  <id>116</id> 
- <title>
- <![CDATA[ Popular Poker - The Popularity of Texas Hold&#39;em
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/online-poker-popularity-texas-holdem
  ]]> 
  </url>
  </item>
- <item>
  <id>364</id> 
- <title>
- <![CDATA[ The Impact of Traditional Poker on Online Poker (and vice versa)
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/online-poker-tradional-vs-online
  ]]> 
  </url>
  </item>
- <item>
  <id>365</id> 
- <title>
- <![CDATA[ The Ultimate, Absolute Online Poker Scandal
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/online-poker-scandal
  ]]> 
  </url>
  </item>
  </items>
- <items>
- <item groupID="27" name="Beginners-Poker" url="/Guides/Online-Poker-Guide/Beginners-Poker/">
- <items>
+ <item>
  <id>101</id> 
- <title>
- <![CDATA[ Poker Betting - All-in On the Flop
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/poker-betting-all-in-on-the-flop
  ]]> 
  </url>
  </item>
+ <item>
  <id>102</id> 
- <title>
- <![CDATA[ Beginners&#39; Poker - Choosing an Online Poker Room
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/beginners-poker-choosing-a-room
  ]]> 
  </url>
  </item>
+ <item>
  <id>105</id> 
- <title>
- <![CDATA[ Beginners&#39; Poker - Choosing What Type of Poker to Play
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/beginners-poker-choosing-type-to-play
  ]]> 
  </url>
  </item>
+ <item>
  <id>106</id> 
- <title>
- <![CDATA[ Online Poker - Different Types of Online Poker
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/online-poker
  ]]> 
  </url>
  </item>
+ <item>
  <id>109</id> 
- <title>
- <![CDATA[ Online Poker - Opening an Account at an Online Poker Site
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/online-poker-opening-an-account
  ]]> 
  </url>
  </item>
+ <item>
  <id>111</id> 
- <title>
- <![CDATA[ Beginners&#39; Poker - Poker Glossary
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/beginners-poker-glossary
  ]]> 
  </url>
  </item>
+ <item>
  <id>117</id> 
- <title>
- <![CDATA[ Poker Betting - What is a Blind?
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/poker-betting-what-is-a-blind
  ]]> 
  </url>
  </item>
- <item>
  <id>118</id> 
- <title>
- <![CDATA[ Poker Betting - What is an Ante?
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/poker-betting-what-is-an-ante
  ]]> 
  </url>
  </item>
+ <item>
  <id>119</id> 
- <title>
- <![CDATA[ Beginners Poker - What is Bluffing?
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/online-poker-what-is-bluffing
  ]]> 
  </url>
  </item>
- <item>
  <id>120</id> 
- <title>
- <![CDATA[ Poker Games - What is Community Card Poker?
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/online-poker-what-is-community-card-poker
  ]]> 
  </url>
  </item>
- <item>
  <id>121</id> 
- <title>
- <![CDATA[ Online Poker - What is Online Poker?
  ]]> 
  </title>
- <url>
- <![CDATA[ /Guides/Online-Poker-Guide/Beginners-Poker/online-poker-what-is-online-poker
  ]]> 
  </url>
  </item>
  </items>
  </item>
  </items>
  </item>
  </items>
  </item>
  </items>

Код XSL:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>

    <xsl:template name="loop">
        <xsl:for-each select="items/item">
            <ul>
            <li><xsl:value-of select="@name" /></li>
            <xsl:if test="@name and child::node()">
                <ul>
                    <xsl:for-each select="items/item">
                        <li><xsl:value-of select="@name" />test</li>
                    </xsl:for-each>
                </ul>
                <xsl:call-template name="loop" />
            </xsl:if>
            <xsl:if test="child::node() and not(@name)">
                <xsl:for-each select="/items">
                    <li><xsl:value-of select="id" /></li>
                </xsl:for-each>
            </xsl:if>
            </ul>
        </xsl:for-each>
        <xsl:for-each select="item/items/item">
            <li>hi</li>
        </xsl:for-each>
    </xsl:template>

    <xsl:template match="/" name="test">
            <xsl:call-template name="loop" />
    </xsl:template>

</xsl:stylesheet>

Я пытаюсь записать XSL так, чтобы каждый <items> узел представит a <ul> и каждый <items> узел представит <li>.

XSL должен быть рекурсивным, потому что я не могу сказать, как глубоко вложенные узлы пойдут.

Кто-либо может помочь?

С уважением, Al

16
задан kennytm 14 May 2010 в 15:57
поделиться

5 ответов

Это просто. Процессор XSLT выполняет всю рекурсию и циклическое за вас, все, что вам нужно сделать, это указать шаблоны для узлов, которые вы хотите обработать.

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <!-- <items> with <item> children becomes <ul> -->
  <xsl:template match="items[item]">
    <ul>
      <xsl:apply-templates select="item" />
    </ul>
  </xsl:template>

  <!-- <items> without <item> children is not handled -->
  <xsl:template match="items[not(item)]" />

  <!-- <item> with @name becomes <li> -->
  <xsl:template match="item[@name]">
    <li>
      <xsl:value-of select ="@name" />
      <xsl:apply-templates select="items" />
    </li>
  </xsl:template>

  <!-- <item> without @name becomes <li>, too -->
  <xsl:template match="item[not(@name)]">
    <li>
      <xsl:value-of select ="id" />
      <xsl:apply-templates select="items" />
    </li>
  </xsl:template>
</xsl:stylesheet>

всегда является рекурсивным/итеративным шагом в XSLT. Он берет все узлы, которые соответствуют его выражению select, и находит для них шаблоны.

Ваша задача состоит в том, чтобы создать соответствующее выражение select, предоставить шаблон для каждого узла, который вы хотите обработать, и в противном случае уйти с дороги. ;-) Сопротивляйтесь желанию втиснуть все в один большой шаблон или использовать только потому, что это удобно - это не так. Отдельные шаблоны создают более многоразовый и поддерживаемый, менее глубоко вложенный код, а процессоры XSLT оптимизированы для обработки шаблонов, поэтому это может быть даже более эффективным подходом.

21
ответ дан 30 November 2019 в 21:18
поделиться

Я думаю, вы можете просто написать XSL-T для сопоставления с . Единственный способ, которым рекурсия будет иметь значение, - это если вы хотите сохранить отношения родитель / потомок. Сопоставления по будет достаточно, если ваше требование состоит в том, чтобы сопоставить каждый из них с маркером в неупорядоченном списке

1
ответ дан 30 November 2019 в 21:18
поделиться

Может быть, что-то вроде этого будет больше тем, что вам нужно?

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="html" indent="yes"/>

  <xsl:template match="items" mode="loop">
    <ul>
      <xsl:for-each select="item">
        <li>
          <xsl:value-of select ="@name" />
          <xsl:value-of select="id" />
          <xsl:for-each select="items">
            <xsl:apply-templates select="." mode="loop" />
          </xsl:for-each>
        </li>
      </xsl:for-each>
    </ul>
  </xsl:template>

  <xsl:template match="/" name="test">
    <xsl:apply-templates select="/items" mode="loop" />
  </xsl:template>
</xsl:stylesheet>
0
ответ дан 30 November 2019 в 21:18
поделиться

Вы должны быть в состоянии сделать это без написания цикла, если я правильно понимаю ваши потребности.

Обычно лучше использовать более декларативный стиль, в данном случае написать шаблон, соответствующий тегу и преобразующий его в

    , а другой, соответствующий , преобразующий его в
  • . Вызов внутри обоих шаблонов обеспечит рекурсию.

3
ответ дан 30 November 2019 в 21:18
поделиться

Следующая таблица стилей выполняет указанное форматирование. Обратите внимание на использование xsl: apply-templates для рекурсии вниз по дереву XML. См. 5.4 Применение шаблонных правил для получения дополнительной информации.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <xsl:apply-templates select="items"/>
    </xsl:template>

    <xsl:template match="items">
        <ul>
            <xsl:apply-templates select="item" />
        </ul>
    </xsl:template>

    <xsl:template match="item">
        <li>
            <xsl:choose>
                <xsl:when test="@name">
                    <xsl:value-of select="@name"/>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="id"/>
                </xsl:otherwise>
            </xsl:choose>
            <xsl:apply-templates select="items" />
        </li>
    </xsl:template>
</xsl:stylesheet>
2
ответ дан 30 November 2019 в 21:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: