开发者

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="'&#10;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;&#9;'"/>

 <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>&#10;</xsl:text>
  <xsl:for-each select="ancestor::ul"><xsl:text>&#9;</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>&#10;</xsl:text>
  <xsl:for-each select="ancestor::ul"><xsl:text>&#9;</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('&#09;*',.,'&#xA;')"/>
    </xsl:template>

    <xsl:template match="li[count(ancestor::ul)=2]">
        <xsl:value-of select="concat('&#09;&#09;#',.,'&#xA;')"/>
    </xsl:template>

    <xsl:template match="li[count(ancestor::ul)=3]">
        <xsl:value-of select="concat('&#09;&#09;'&#09;-',.,'&#xA;')"/>
    </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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜