HTML 列表 - XSLT 每个循环多个嵌套
我正在尝试从 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 示例以帮助其他人。
谢谢你!
I'm trying to generate a multi level nested html list from xml/xsl.
For example, a preferred html output would be:
<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>
My poor attempt 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>
This is what I'm getting below... Notice that when there's a level 3 item then all of items have merged and then displaying under both.
<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>
Please provide me with 1.0 solutions and then of course show 2.0 examples to help others as well.
thank you!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这是一个适用于您的输入 XML 的 XSLT 1.0 解决方案。
给定您问题中的输入文档,它会产生以下输出:
坦率地说,我现在太累了,无法详细解释解决方案。不过我留下了一些评论。可以说它相当复杂。
如果您的 XML 如下所示(即正确嵌套):
生成与上面相同的 HTML 结果的解决方案将如下所示:
Here is an XSLT 1.0 solution that works with your input XML.
Given the input document from your question, it produces this output:
Frankly, I'm too tired right now to explain the solution in detail. I've left a few comments though. Suffice it to say that it is pretty complicated.
If your XML would look like this (i.e. properly nested):
a solution that would produce the same HTML result as above would look like this:
尝试下面的方法。
说明:选择前面具有相同第一个“两个”同级的所有“三个”同级。
我在 XML Spy 中运行它并获得了想要的输出(参见下面的 xslt)。
输出:
Try the below.
Explanation: select all "three" siblings that have the same first "two" sibling preceding it.
I ran this in XML Spy and got the wanted output (see below xslt).
Output:
这种简单(没有内联 XML、没有
document()
和contains()
函数)、简短而高效的转换:当应用于提供的 XML 文档:
产生所需的正确结果:
浏览器显示为:
解释:
有一个键
kFollowing
(具有两个单独的定义)通过其逻辑父元素的generate-id()
值(分别为one
或两个
)。这有助于我们拥有一个同时匹配one
和two
元素的模板。每个组中第一(
two
或two
)元素均在无模式下进行匹配和处理。在此模板中,生成了包装ul
,然后组中的所有元素(作为参数传递)都以名为inGroup
的模式进行处理。This simple (no inline XML, no
document()
andcontains()
functions), short and efficient transformation:when applied on the provided XML document:
produces the wanted, correct result:
and it is displayed by the browser as:
Explanation:
There is a single key
kFollowing
(with two separate definitions) that indexes anytwo
orthree
element by the value ofgenerate-id()
of its logical parent (respectivelyone
ortwo
). This helps us to have a single template matching bothone
andtwo
elements.Every first-in-group (
two
orthree
) element is matched and processed in no mode. In this template the wrappingul
is generated, then all elements in the group (passed as a parameter) are processed in mode namedinGroup
.