这是根据层次结构嵌套节点的简单方法:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/XML_FILTER">
<ul>
<xsl:apply-templates select="XPATH[not(contains(@xpath, '/'))]"/>
</ul>
</xsl:template>
<xsl:template match="XPATH">
<xsl:variable name="dir" select="concat(@xpath, '/')" />
<li>
<xsl:value-of select="@xpath"/>
</li>
<xsl:variable name="child" select="../XPATH[starts-with(@xpath, $dir) and not(contains(substring-after(@xpath, $dir), '/'))]" />
<xsl:if test="$child">
<ul>
<xsl:apply-templates select="$child"/>
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
应用于您的示例输入(@
从属性名称中删除非法字符后!),结果将是:
<?xml version="1.0" encoding="UTF-8"?>
<ul>
<li>root</li>
<ul>
<li>root/1stGenChild1</li>
<ul>
<li>root/1stGenChild1/2ndGenChild1</li>
<li>root/1stGenChild1/2ndGenChild2</li>
</ul>
<li>root/1stGenChild2</li>
</ul>
</ul>
现在您只需要更换:
<xsl:value-of select="@xpath"/>
调用返回最后一个令牌的命名模板的指令 - 请参阅:https ://stackoverflow.com/a/41625340/3016153
或者改为这样做:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/XML_FILTER">
<ul>
<xsl:apply-templates select="XPATH[not(contains(@xpath, '/'))]"/>
</ul>
</xsl:template>
<xsl:template match="XPATH">
<xsl:param name="parent"/>
<xsl:variable name="dir" select="concat(@xpath, '/')" />
<li>
<xsl:value-of select="substring-after(concat('/', @xpath), concat($parent, '/'))"/>
</li>
<xsl:variable name="child" select="../XPATH[starts-with(@xpath, $dir) and not(contains(substring-after(@xpath, $dir), '/'))]" />
<xsl:if test="$child">
<ul>
<xsl:apply-templates select="$child">
<xsl:with-param name="parent" select="concat('/', @xpath)"/>
</xsl:apply-templates>
</ul>
</xsl:if>
</xsl:template>
</xsl:stylesheet>