开发者

Nested list with number labels

开发者 https://www.devze.com 2023-04-01 08:52 出处:网络
I have a nested list, and therefore I want the label to be nested too. This is my code: <!-- For first list -->

I have a nested list, and therefore I want the label to be nested too.

This is my code:

<!-- For first list -->
<xsl:template name="list1-label">
    <xsl:number format="1."/>
</xsl:template>

<!-- The nestled list -->
<xsl:template name="list2-label">
    <xsl:number format="1.1."/>
</xsl:template>

The first number in the last template (1.1.) I want to be relative to the parent item, in this case; "3".

Here is the xml structure:

<list1>
  <item>Test</item>
  <开发者_如何学编程item>Test</item>
  <list2>
    <item>Test</item>
    <item>Test</item>
  </list2>
  <item>Test</item>
</list1>

Here is the output:

1. Test
2. Test
    2.1. Test
    2.2. Test
3. Test


The wanted output can be obtained (for example) applying the advanced attributes @from and @count of xsl:number. Here a working example from which you should get started:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="list1/item">  
        <xsl:number level="any" from="list1" count="list1/item"/>
        <xsl:text>. </xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

    <xsl:template match="list1/list2/item">
        <xsl:text>&#09;</xsl:text>
        <xsl:number level="any" from="list1" count="list1/item"/>
        <xsl:text>.</xsl:text>
        <xsl:number level="any" from="list2" count="list2/item"/>
        <xsl:text>. </xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>&#10;</xsl:text>
    </xsl:template>

</xsl:stylesheet>

If you want to simplify the match patterns:

<xsl:template match="list1">
    <xsl:apply-templates />
</xsl:template>

<xsl:template match="list1/item">  
    <xsl:number level="any" from="list1" count="list1/item"/>
    <xsl:text>. </xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>&#10;</xsl:text>
</xsl:template>

<xsl:template match="list2/item">
    <xsl:text>&#09;</xsl:text>
    <xsl:number level="any" from="list1" count="list1/item"/>
    <xsl:text>.</xsl:text>
    <xsl:number level="any" from="list2" count="list2/item"/>
    <xsl:text>. </xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>&#10;</xsl:text>
</xsl:template>

This latest example will correctly drive you to further nesting levels as with a list3.


For the nested list you should probably be using level="multiple" count="X|Y" but I can't be more precise than that without knowing (a) what your XML source looks like, and (b) what the context item is at the point where your named templates are called.


This new transform is generalized to handle a variable number of lists.

Input sample:

<list1>
  <item>Test</item>
  <item>Test</item>
  <list2>
        <item>Test</item>
        <list3>
            <item>Test</item>
            <item>Test</item>
        </list3>
        <item>Test</item>
        <list3>
            <item>Test</item>
        </list3>
        <item>Test</item>
  </list2>
  <item>Test</item>
</list1>

transform:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="*[starts-with(name(),'list')]">
        <xsl:apply-templates>
            <xsl:with-param name="tab" select="true()"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="item">
        <xsl:param name="lvl" select="count(ancestor::*)"/>
        <xsl:param name="tab" select="false()"/>

        <!-- insert entry point tab -->
        <xsl:apply-templates select="text()[$tab and $lvl > 1]" mode="tab">
            <xsl:with-param name="lvl" select="$lvl - 1"/>
        </xsl:apply-templates>

        <!-- recurse levels -->
        <xsl:variable name="name" select="name(ancestor::*[$lvl])"/>
        <xsl:number level="any" from="*[name()=$name]" 
            count="*[name()=$name]/item"/>
        <xsl:text>.</xsl:text>
        <xsl:apply-templates select="self::item[$lvl > 1]">
            <xsl:with-param name="lvl" select="$lvl - 1"/>
        </xsl:apply-templates>

        <!-- print value -->
        <xsl:if test="$lvl = 1">
            <xsl:text> </xsl:text>
            <xsl:value-of select="."/>
            <xsl:text>&#10;</xsl:text>
        </xsl:if>
    </xsl:template>

    <xsl:template match="text()" mode="tab">
        <xsl:param name="lvl"/>
        <xsl:text>&#09;</xsl:text>
        <xsl:apply-templates select="self::text()[$lvl>1]" mode="tab">
            <xsl:with-param name="lvl" select="$lvl - 1"/>
        </xsl:apply-templates>
    </xsl:template>

</xsl:stylesheet>

output:

1. Test
2. Test
    2.1. Test
        2.1.1. Test
        2.1.2. Test
    2.2. Test
        2.2.1. Test
    2.3. Test
3. Test
0

精彩评论

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

关注公众号