我是XSLT的新手,在尝试格式化具有递归节点的XML文档时遇到了一些问题。
我的XML代码:
希望我的XML显示:
<item>
都与<items>
<item>
节点嵌套的级别可以是非常深的<?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' 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'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' 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' 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' 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>
节点都呈现<ul>
,每个<items>
节点将呈现<li>
。
XSL需要递归,因为我无法知道嵌套节点的深度。
有人可以帮忙吗?
此致 人
答案 0 :(得分:21)
这很容易。 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>
<xsl:apply-templates>
始终是XSLT中的递归/迭代步骤。它需要任何符合其select
表达式的节点并为它们找到模板。
你的工作就是制作一个合适的select
表达式,为你想要处理的每个节点提供一个模板,否则就会让它失控。 ;-)抵制将所有东西塞进一个大模板或使用<xsl:for-each>
的冲动,因为它感觉方便 - 事实并非如此。单独的模板创建了更多可重用和可维护,嵌套程度较低的代码,并且XSLT处理器针对模板处理进行了优化,因此这甚至可能是更有效的方法。
答案 1 :(得分:3)
如果我正确理解您的需求,您应该能够在不编写循环的情况下执行此操作。
通常最好使用更具声明性的样式,在这种情况下,编写一个匹配<items>
标记的模板并将其转换为<ul>
,另一个匹配<item>
将其转换为{ {1}}。
答案 2 :(得分:2)
以下样式表执行指定的格式。请注意使用xsl:apply-templates
来递减XML树。有关详细信息,请参阅5.4 Applying Template Rules。
<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>
答案 3 :(得分:1)
我认为您可以编写XSL-T以匹配<item>
。如果你想保留父/子关系,那么递归的唯一方法就是重要。如果您的要求是将每个要素映射到无序列表中的项目符号,则<item>
上的匹配就足够了
答案 4 :(得分:0)
这样的事情会更像你所追求的吗?
<?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>