XSLT1: convert XML nodes to Html list, by starting from the deepest node first
I have this below xml
<root>
<s>
<name>self-1</name>
<parents>
<s>
<name>p-1-2</name>
<parents>
<s>
<name>p-1-2-1</name>
<parents>
<s>
<name>p-1-2-1-1</name>
</s>
</parents>
</s>
<s>
<name>p-1-2-2</name>
</s>
</parents>
</s>
</parents>
</s>
</root>
and I need to write an xslt1 to parse that xml to produce output like below, the goal is to process all parents nodes first and finally the node self-1. Please give me some advice.
<ul>
<li>p-1-2-1-1</li>
<ul>
<li>p-1-2-1</li>
<li>p-1-2-2</li>
<ul>
<li>p-1-2</li>
<ul>
<!-- self -->
<li>self-1</li>
</ul>
开发者_运维问答 </ul>
</ul>
</ul>
Here is my suggestion on how to solve that:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="descendant::parents[not(s/parents)]"/>
</xsl:template>
<xsl:template match="parents | root">
<ul>
<xsl:apply-templates select="s/name"/>
<xsl:variable name="p" select="parent::s/parent::parents | parent::s/parent::root"/>
<xsl:if test="$p">
<li>
<xsl:apply-templates select="$p"/>
</li>
</xsl:if>
</ul>
</xsl:template>
<xsl:template match="name">
<li>
<xsl:value-of select="."/>
</li>
</xsl:template>
</xsl:stylesheet>
That outputs
<ul>
<li>p-1-2-1-1</li>
<li>
<ul>
<li>p-1-2-1</li>
<li>p-1-2-2</li>
<li>
<ul>
<li>p-1-2</li>
<li>
<ul>
<li>self-1</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
That is not exactly what you asked for, but that is done intentionally: your sample had ul
elements with ul
children but that is not allowed in HTML(http://www.w3.org/TR/html4/struct/lists.html#h-10.2). So my stylesheet makes sure the result is valid HTML by making sure any ul
has only li
child elements.
to handle multile node <s>
I updated the template <xsl:template match="parents | root">
to something like below:
<xsl:template match="parents | root">
<ul>
<xsl:apply-templates select="s/name"/>
<xsl:choose>
<xsl:when test="parent::s/parent::parents">
<xsl:variable name="p" select="parent::s/parent::parents"/>
<li><xsl:apply-templates select="$p"/></li>
</xsl:when>
<xsl:when test="parent::s/parent::root">
<xsl:variable name="p" select="parent::s/parent::root"/>
<li><xsl:apply-templates select="$p"/></li>
</xsl:when>
</xsl:choose>
</ul>
</xsl:template>
精彩评论