如何在嵌套之后和使用level ="任何"时恢复xsl数量计数

时间:2016-07-06 19:10:33

标签: xslt xslt-2.0

我想让<xsl:number/>恢复其计数器。但是,由于它使用level="any",因此它会计算其先前兄弟元素的元素,这是不可取的。

使用下面的示例代码,除了包含ThreeFour的列表项外,一切看起来都是正确的。这些项目的数量为5和6,因为计数器使用项目Two中嵌套的项目,而不是从项目Two本身停止的位置继续。

示例输入XML:

<body>
    <div class="list-wrapper">
        <ol>
            <li>One</li>
            <li><span>Two</span>
                <ol>
                    <li>AAA</li>
                    <li>BBB</li>
                </ol>
                <div class="list-wrapper">
                    <ol>
                        <li>CCC</li>
                        <li>DDD</li>
                    </ol>
                    <ol>
                        <li>EEE</li>
                        <li>FFF</li>
                    </ol>
                </div>
                <ol>
                    <li>GGG</li>
                    <li>HHH</li>
                </ol>
            </li>
        </ol>
        <ol>
            <li>Three</li>
            <li>Four</li>
        </ol>
    </div>
    <div class="list-wrapper">
        <ol>
            <li>Five</li>
            <li>Six</li>
        </ol>
        <ol>
            <li>Seven</li>
            <li>Eight</li>
        </ol>
    </div>
</body>

示例样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="body">
        <fo:root>
            <xsl:apply-templates />
        </fo:root>
    </xsl:template>

    <xsl:template match="div[@class='list-wrapper']">
        <fo:list-block>
            <xsl:apply-templates  mode="list-wrapper" />
        </fo:list-block>
    </xsl:template>

    <xsl:template match="ol" mode="list-wrapper">
        <xsl:apply-templates mode="list-wrapper" />
    </xsl:template>

    <xsl:template match="li" mode="list-wrapper">
        <fo:list-item>
            <fo:list-item-label>
                <xsl:number format="1." count="div[@class='list-wrapper']/ol/li" from="div[@class='list-wrapper']" level="any" />
            </fo:list-item-label>
            <fo:list-item-body>
                <xsl:apply-templates />
            </fo:list-item-body>
        </fo:list-item>
    </xsl:template>

    <xsl:template match="ol">
        <fo:list-block>
            <xsl:apply-templates />
        </fo:list-block>
    </xsl:template>

    <xsl:template match="li">
        <fo:list-item>
            <fo:list-item-label>
                <xsl:number format="1."/>
            </fo:list-item-label>
            <fo:list-item-body>
                <xsl:apply-templates />
            </fo:list-item-body>
        </fo:list-item>
    </xsl:template>
</xsl:stylesheet>

2 个答案:

答案 0 :(得分:0)

通过使用xsl:for-each仅处理div[@class='list-wrapper']的直接子项,我似乎可以解决嵌套问题。

现在我可以根据需要使用position()为每个节点编号。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="body">
        <fo:root>
            <xsl:apply-templates />
        </fo:root>
    </xsl:template>

    <xsl:template match="div[@class='list-wrapper']">
        <fo:list-block>
            <xsl:for-each select="ol/li">
                <xsl:call-template name="process-ordered-list" />
            </xsl:for-each>
        </fo:list-block>
    </xsl:template>

    <xsl:template match="li">
        <xsl:call-template name="process-ordered-list" />
    </xsl:template>

    <xsl:template name="process-ordered-list">
        <fo:list-item>
            <fo:list-item-label>
                <xsl:number format="1." value="position()" />
            </fo:list-item-label>
            <fo:list-item-body>
                <xsl:apply-templates />
            </fo:list-item-body>
        </fo:list-item>
    </xsl:template>

    <xsl:template match="ol">
        <fo:list-block>
            <xsl:apply-templates />
        </fo:list-block>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

我可以将for-each替换为apply-templates来简化模板。

此解决方案效果最佳。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="body">
        <fo:root>
            <xsl:apply-templates />
        </fo:root>
    </xsl:template>

    <xsl:template match="div[@class='list-wrapper']">
        <fo:list-block>
            <xsl:apply-templates select="ol/li" />
        </fo:list-block>
    </xsl:template>

    <xsl:template match="ol">
        <fo:list-block>
            <xsl:apply-templates />
        </fo:list-block>
    </xsl:template>

    <xsl:template match="ol/li">
        <fo:list-item>
            <fo:list-item-label>
                <xsl:number format="1." value="position()" />
            </fo:list-item-label>
            <fo:list-item-body>
                <xsl:apply-templates />
            </fo:list-item-body>
        </fo:list-item>
    </xsl:template>
</xsl:stylesheet>