XSLT Transforming XML into a cross referenced, nested HTML lists when source nodes are siblings and nesting is based on attribute values 源节点是兄弟节点且嵌套基于属性值时
XSLT Transforming XML into a cross referenced, nested HTML lists when source nodes are siblings and nesting is based on attribute values
问题:我需要从 XML 创建一个嵌套的 HTML 无序列表,这不是嵌套的。此外,我需要将 XML 与文档中也包含的 'allowed nodes' 部分进行交叉引用。
示例XML:
<content>
<data>
<navigation>
<link name="about us" url="#"/>
<link name="staff" url="staff.asp" parent="about us"/>
<link name="contact" url="contact.asp" parent="about us"/>
<link name="facebook" url="facebook.asp"/>
</navigation>
</data>
<allowedlinks>
<link name="about us"/>
<link name="facebook"/>
</allowedlinks>
</content>
示例结果HTML(注意我已经省略了样板代码):
<ul>
<li>
about us
<ul>
<li>staff</li>
<li>contact</li>
</ul>
</li>
<li>facebook</li>
</ul>
最终这将在网站上形成一个导航菜单。
规则:
-我需要使用 XSLT 1.0 来创建解决方案。
-如果 link 存在,我需要将它添加到 UL 并创建任何嵌套的子 UL,如果任何兄弟包含当前节点 @name 的@parent。
-任何没有@parent的节点在生成LI item之前,必须先确认其@name匹配允许的links段中的一个link@name .
在我看来 - 被转换的 XML 的结构真的很愚蠢并且使转换过程过于复杂 - 但是由于我无法更改原始 XML,我需要一个解决方案.
注意 - 我已经有了一个可行的答案,我很快就会 post。我想先看看其他可能的答案:)
如果这可以通过模板匹配完成并且每个循环都不会太多,则奖励。
我的解决方案包含 2 个我不喜欢的嵌套 for-each。
这是使用键的经典案例:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:key name="allowed-link" match="allowedlinks/link" use="@name" />
<xsl:key name="link-by-parent" match="link" use="@parent" />
<xsl:template match="/content">
<ul>
<xsl:apply-templates select="data/navigation/link[not(@parent) and key('allowed-link', @name)]"/>
</ul>
</xsl:template>
<xsl:template match="link">
<li>
<xsl:value-of select="@name"/>
<xsl:variable name="sublinks" select="key('link-by-parent', @name)" />
<xsl:if test="$sublinks">
<ul>
<xsl:apply-templates select="$sublinks"/>
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>
问题:我需要从 XML 创建一个嵌套的 HTML 无序列表,这不是嵌套的。此外,我需要将 XML 与文档中也包含的 'allowed nodes' 部分进行交叉引用。
示例XML:
<content>
<data>
<navigation>
<link name="about us" url="#"/>
<link name="staff" url="staff.asp" parent="about us"/>
<link name="contact" url="contact.asp" parent="about us"/>
<link name="facebook" url="facebook.asp"/>
</navigation>
</data>
<allowedlinks>
<link name="about us"/>
<link name="facebook"/>
</allowedlinks>
</content>
示例结果HTML(注意我已经省略了样板代码):
<ul>
<li>
about us
<ul>
<li>staff</li>
<li>contact</li>
</ul>
</li>
<li>facebook</li>
</ul>
最终这将在网站上形成一个导航菜单。
规则: -我需要使用 XSLT 1.0 来创建解决方案。
-如果 link 存在,我需要将它添加到 UL 并创建任何嵌套的子 UL,如果任何兄弟包含当前节点 @name 的@parent。
-任何没有@parent的节点在生成LI item之前,必须先确认其@name匹配允许的links段中的一个link@name .
在我看来 - 被转换的 XML 的结构真的很愚蠢并且使转换过程过于复杂 - 但是由于我无法更改原始 XML,我需要一个解决方案.
注意 - 我已经有了一个可行的答案,我很快就会 post。我想先看看其他可能的答案:)
如果这可以通过模板匹配完成并且每个循环都不会太多,则奖励。
我的解决方案包含 2 个我不喜欢的嵌套 for-each。
这是使用键的经典案例:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:key name="allowed-link" match="allowedlinks/link" use="@name" />
<xsl:key name="link-by-parent" match="link" use="@parent" />
<xsl:template match="/content">
<ul>
<xsl:apply-templates select="data/navigation/link[not(@parent) and key('allowed-link', @name)]"/>
</ul>
</xsl:template>
<xsl:template match="link">
<li>
<xsl:value-of select="@name"/>
<xsl:variable name="sublinks" select="key('link-by-parent', @name)" />
<xsl:if test="$sublinks">
<ul>
<xsl:apply-templates select="$sublinks"/>
</ul>
</xsl:if>
</li>
</xsl:template>
</xsl:stylesheet>