XSLT nested list items
I am new to xslt, I trying to deal with a situation where I have nested unordered or ordered list items eg:
* Dresses
# Formal
- Men
- Women
- Children
# Casual
* FootWear
* Other Accessories
Basically the list items are nested one within other but we they can nested as deep as it can be. Can you give me a general idea on how to achieve this..
Edith says: Thanks for your quick response.Here is my xml:
<?xml version="1.0" encoding="utf-8"?>
<emailmessage>
<ul>
开发者_JS百科 <li>Dresses</li>
<ul>
<li>Professional</li>
<ul>
<li>Mens</li>
<li>Womens</li>
</ul>
<li>Causual </li>
</ul>
<li>FootWear</li>
<li>Other Accessories</li>
</ul>
</emailmessage>
This is my xml in html type, the format is something I want to attain in plain text i.e
- One tab and
*
if its<li>
without any ancestor - two tabs and
#
if its sublist of first one i.e one having one ancestor - three tabs with
-
if its sublist of sublist i.e has two ancestors.
And the format repeats..
* Dresses
# Formal
- Men
- Women
- Children
# Casual
* FootWear
* Other Accessories
This transformation works with any level of nestedness, up to 20:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vIndent"
select="' 																				'"/>
<xsl:template match="li">
<xsl:value-of select=
"concat(substring($vIndent,1, count(ancestor::ul)+1),.)"/>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<emailmessage>
<ul>
<li>* Dresses</li>
<ul>
<li># Professional</li>
<ul>
<li>- Mens</li>
<li>- Womens</li>
</ul>
<li># Causual </li>
</ul>
<li>* FootWear</li>
<li>* Other Accessories</li>
</ul>
</emailmessage>
produces the wanted, correct result:
* Dresses
# Professional
- Mens
- Womens
# Causual
* FootWear
* Other Accessories
Update: unlimited nesting:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="li">
<xsl:text> </xsl:text>
<xsl:for-each select="ancestor::ul"><xsl:text>	</xsl:text></xsl:for-each>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Update2: The OP has indicated that the marking characters (*, *, and -) aren't present in the XML document. Here is the solution that works with unlimited nesting:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vDelims" select="'- * # '"/>
<xsl:template match="li">
<xsl:text> </xsl:text>
<xsl:for-each select="ancestor::ul"><xsl:text>	</xsl:text></xsl:for-each>
<xsl:value-of select=
"substring($vDelims,
2*(1+count(ancestor::ul) mod 3) -1,
2)"/>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
When applied on the provided XML document (as above but with bullet characters removed):
<emailmessage>
<ul>
<li>Dresses</li>
<ul>
<li>Professional</li>
<ul>
<li>Mens</li>
<li>Womens</li>
</ul>
<li>Causual </li>
</ul>
<li>FootWear</li>
<li>Other Accessories</li>
</ul>
</emailmessage>
the same, wanted and correct result is produced:
* Dresses
# Professional
- Mens
- Womens
# Causual
* FootWear
* Other Accessories
Count the ul ancestors on template match (note that the first one does not need it). This transform should give you a good starting point:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="emailmessage/ul/li">
<xsl:value-of select="concat('	*',.,'
')"/>
</xsl:template>
<xsl:template match="li[count(ancestor::ul)=2]">
<xsl:value-of select="concat('		#',.,'
')"/>
</xsl:template>
<xsl:template match="li[count(ancestor::ul)=3]">
<xsl:value-of select="concat('		'	-',.,'
')"/>
</xsl:template>
</xsl:stylesheet>
produces:
* Dresses
# Professional
- Mens
- Womens
# Causual
* FootWear
* Other Accessories
Maybe this example can be helpful? It shows how to build a tree-navigation for a website with XSLT.
精彩评论