我正在尝试从xml/xsl生成一个多层嵌套的html列表。
例如,首选的html输出为:
<ul>
<li>Level 1 - Item 1</li>
<ul>
<li>Level 2 - Item 1-1</li>
<li>Level 2 - Item 1-2</li>
</ul>
<li> Level 1 - Item 2</li>
<ul>
<li>Level 2 - Item 2-1
<ul>
<li>Level 3 - Item 2-1-1</li>
<li>Level 3 - Item 2-1-2</li>
<li>Level 3 - Item 2-1-3</li>
</ul>
</li>
<li>Level 2 - Item 2-2
<ul>
<li>Level 3 - Item 2-2-1</li>
<li>Level 3 - Item 2-2-2</li>
</ul>
</li>
</ul>XML:
<doc>
<item>
<one>Level 1 - Item 1</one>
<two>Level 2 - Item 1-1</two>
<two>Level 2 - Item 1-2</two>
</item>
<item>
<one>Level 2 - Item 2</one>
<two>Level 2 - Item 2-1</two>
<three>Level 3 - Item 2-1-1</three>
<three>Level 3 - Item 2-1-2</three>
<three>Level 3 - Item 2-1-3</three>
<two>Level 2 - Item 2-2</two>
<three>Level 3 - Item 2-2-1</three>
<three>Level 3 - Item 2-2-2</three>
</item>
</doc>我糟糕的XSL尝试:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="doc/item">
<li><xsl:value-of select="one" />
<ul>
<xsl:for-each select="two">
<li><xsl:value-of select="."/>
<xsl:for-each select="../three"><ul><li><xsl:value-of select="."/></li></ul></xsl:for-each>
</li>
</xsl:for-each>
</ul>
</li>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>这是我在下面得到的..。请注意,当有一个3级项目时,所有项目都已合并,然后显示在两者之下。
<li>Level 1 - Item 1<ul>
<li>Level 2 - Item 1-1</li>
<li>Level 2 - Item 1-2</li>
</ul>
</li>
<li>Level 2 - Item 2<ul>
<li>Level 2 - Item 2-1<ul>
<li>Level 3 - Item 2-1-1</li>
</ul>
<ul>
<li>Level 3 - Item 2-1-2</li>
</ul>
<ul>
<li>Level 3 - Item 2-1-3</li>
</ul>
<ul>
<li>Level 3 - Item 2-2-1</li>
</ul>
<ul>
<li>Level 3 - Item 2-2-2</li>
</ul>
</li>
<li>Level 2 - Item 2-2<ul>
<li>Level 3 - Item 2-1-1</li>
</ul>
<ul>
<li>Level 3 - Item 2-1-2</li>
</ul>
<ul>
<li>Level 3 - Item 2-1-3</li>
</ul>
<ul>
<li>Level 3 - Item 2-2-1</li>
</ul>
<ul>
<li>Level 3 - Item 2-2-2</li>
</ul>
</li>
</ul>
</li>请为我提供1.0的解决方案,然后当然显示2.0的例子,以帮助他人以及。
谢谢!
发布于 2012-02-03 08:23:08
下面是一个处理输入XML的XSLT 1.0解决方案。
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="http://tempuri.org"
exclude-result-prefixes="my"
>
<xsl:output indent="yes" />
<!-- define which elements are where in the hierarchy -->
<my:level name="one" higher="" deeper="two,three" />
<my:level name="two" higher="one" deeper="three" />
<my:level name="three" higher="one,two" deeper="" />
<xsl:template match="doc">
<body>
<xsl:apply-templates mode="ul" select="item/*[1]" />
</body>
</xsl:template>
<xsl:template match="one|two|three" mode="ul">
<ul>
<xsl:apply-templates mode="li" select="." />
</ul>
</xsl:template>
<xsl:template match="one|two|three" mode="li">
<xsl:variable name="myName" select="name()" />
<xsl:variable name="myID" select="generate-id()" />
<!-- select the appropriate hierarchy info for this node -->
<xsl:variable name="level" select="
document('')/*/my:level[@name = $myName]
" />
<li>
<xsl:value-of select="." />
<!-- create <ul> if immediately follwing sibling is deeper -->
<xsl:apply-templates mode="ul" select="
following-sibling::*[1][contains($level/@deeper, name())]
" />
</li>
<!-- process contiguous following siblings of same level -->
<xsl:apply-templates mode="li" select="
following-sibling::*[name() = $myName][
generate-id(
preceding-sibling::*[contains($level/@higher, name())][1]/following-sibling::*[1]
)
= $myID
]
" />
</xsl:template>
</xsl:stylesheet>给定问题中的输入文档,它将生成以下输出:
<body>
<ul>
<li>Level 1 - Item 1
<ul>
<li>Level 2 - Item 1-1</li>
<li>Level 2 - Item 1-2</li>
</ul>
</li>
</ul>
<ul>
<li>Level 2 - Item 2
<ul>
<li>Level 2 - Item 2-1
<ul>
<li>Level 3 - Item 2-1-1</li>
<li>Level 3 - Item 2-1-2</li>
<li>Level 3 - Item 2-1-3</li>
</ul>
</li>
<li>Level 2 - Item 2-2
<ul>
<li>Level 3 - Item 2-2-1</li>
<li>Level 3 - Item 2-2-2</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>坦率地说,我现在太累了,无法详细解释解决方案。不过,我还是留下了一些评论。可以说,这是相当复杂的。
如果您的XML看起来像这样(即正确嵌套):
<doc>
<item title="Level 1 - Item 1">
<item title="Level 2 - Item 1-1" />
<item title="Level 2 - Item 1-2" />
</item>
<item title="Level 2 - Item 2">
<item title="Level 2 - Item 2-1">
<item title="Level 3 - Item 2-1-1" />
<item title="Level 3 - Item 2-1-2" />
<item title="Level 3 - Item 2-1-3" />
</item>
<item title="Level 2 - Item 2-2">
<item title="Level 3 - Item 2-2-1" />
<item title="Level 3 - Item 2-2-2" />
</item>
</item>
</doc>将产生与上面相同的HTML结果的解决方案将如下所示:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output indent="yes" />
<xsl:template match="doc">
<body>
<xsl:for-each select="item">
<ul>
<xsl:apply-templates select="." />
</ul>
</xsl:for-each>
</body>
</xsl:template>
<xsl:template match="item">
<li>
<xsl:value-of select="@title" />
<xsl:if test="item">
<ul>
<xsl:apply-templates select="item" />
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>发布于 2012-02-03 08:41:24
试试下面的方法。说明:选择前面有相同的前两个同级的所有“三个”同级。我在XML中运行了这段代码,并获得了所需的输出(参见下面的xslt)。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="doc/item">
<li>
<xsl:value-of select="one" />
<ul>
<xsl:for-each select="two">
<li>
<xsl:value-of select="."/>
<ul>
<xsl:for-each select="following-sibling::three[preceding-sibling::two[1]=current()]">
<li>
<xsl:value-of select="."/>
</li>
</xsl:for-each>
</ul>
</li>
</xsl:for-each>
</ul>
</li>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>输出:
<html>
<body>
<li>Level 1 - Item 1
<ul>
<li>Level 2 - Item 1-1
<ul></ul>
</li>
<li>Level 2 - Item 1-2
<ul></ul>
</li>
</ul>
</li>
<li>Level 2 - Item 2
<ul>
<li>Level 2 - Item 2-1
<ul>
<li>Level 3 - Item 2-1-1</li>
<li>Level 3 - Item 2-1-2</li>
<li>Level 3 - Item 2-1-3</li>
</ul>
</li>
<li>Level 2 - Item 2-2
<ul>
<li>Level 3 - Item 2-2-1</li>
<li>Level 3 - Item 2-2-2</li>
</ul>
</li>
</ul>
</li>
</body>
</html>发布于 2012-02-03 11:17:38
这个转换很简单(没有内联XML,没有document() 和document()函数),简短而高效的转换
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing" match="two"
use="generate-id(preceding-sibling::one[1])"/>
<xsl:key name="kFollowing" match="three"
use="generate-id(preceding-sibling::two[1])"/>
<xsl:template match="/*">
<ul>
<xsl:apply-templates select="item/one" mode="inGroup"/>
</ul>
</xsl:template>
<xsl:template match="one|two" mode="inGroup">
<li><xsl:value-of select="concat(., '
')"/>
<xsl:variable name="vGroup" select=
"key('kFollowing', generate-id())"/>
<xsl:apply-templates select=
"$vGroup[1]">
<xsl:with-param name="pGroup" select="$vGroup"/>
</xsl:apply-templates>
</li>
</xsl:template>
<xsl:template match="two|three">
<xsl:param name="pGroup"/>
<xsl:if test="position() = 1">
<ul>
<xsl:apply-templates select="$pGroup" mode="inGroup"/>
</ul>
</xsl:if>
</xsl:template>
<xsl:template match="three" mode="inGroup">
<li><xsl:value-of select="."/></li>
</xsl:template>
</xsl:stylesheet>在所提供的XML文档上应用时的
<doc>
<item>
<one>Level 1 - Item 1</one>
<two>Level 2 - Item 1-1</two>
<two>Level 2 - Item 1-2</two>
</item>
<item>
<one>Level 2 - Item 2</one>
<two>Level 2 - Item 2-1</two>
<three>Level 3 - Item 2-1-1</three>
<three>Level 3 - Item 2-1-2</three>
<three>Level 3 - Item 2-1-3</three>
<two>Level 2 - Item 2-2</two>
<three>Level 3 - Item 2-2-1</three>
<three>Level 3 - Item 2-2-2</three>
</item>
</doc>生成所需的、正确的结果
<ul>
<li>Level 1 - Item 1
<ul>
<li>Level 2 - Item 1-1
</li>
<li>Level 2 - Item 1-2
</li>
</ul>
</li>
<li>Level 2 - Item 2
<ul>
<li>Level 2 - Item 2-1
<ul>
<li>Level 3 - Item 2-1-1</li>
<li>Level 3 - Item 2-1-2</li>
<li>Level 3 - Item 2-1-3</li>
</ul>
</li>
<li>Level 2 - Item 2-2
<ul>
<li>Level 3 - Item 2-2-1</li>
<li>Level 3 - Item 2-2-2</li>
</ul>
</li>
</ul>
</li>
</ul>,浏览器将其显示为
- Level 2 - Item 2-2
- Level 3 - Item 2-2-1
- Level 3 - Item 2-2-2说明
kFollowing (有两个独立的定义),它根据逻辑父元素(分别是one或two)的generate-id()值对任何two或three元素进行索引。这有助于我们拥有一个同时匹配one和two的模板elements.two或three)元素被匹配并在no模式下处理。在此模板中,将生成包装ul,然后在名为inGroup.的模式下处理组中的所有元素(作为参数传递
https://stackoverflow.com/questions/9119927
复制相似问题