使用xsl:number元素时,开始计数为零而不是一

时间:2017-05-05 09:21:58

标签: xml xslt xpath xslt-1.0

修改
我想我仍然使用XSLT 1.0时找到了a way around this issue,虽然非常冗长并且可能容易出错。

有没有办法使用<xsl:number>元素,但是从0开始计数而不是1,尤其是在使用level="multiple"时?

我正在使用XSLT 1.0。

当前结果:1.2.2. Subitem_B
预期结果:0.1.1. Subitem_B

我尝试了format="0",但它只输出了点数(即... Subitem_B

<xsl:number level="multiple" format="0. "/>

奖金问题: 我找到了使用translate($number,'.','-')的方法,但我仍然很想知道是否有一种方法可以使用自定义字符而不是点作为分隔符,甚至是自定义format。< / p>

XML输入

<?xml version='1.0'?>
<?xml-stylesheet type="text/xsl" href="stylesheet.xsl" version="1.0"?>
<root>
  <item>Main_A
    <item>Item_A</item>
    <item>Item_B
      <item>Subitem_A</item>
      <item>Subitem_B</item>
    </item>
    <item>Item_C</item>
  </item>
  <item>Main_B
    <item>Item_A
      <item>Subitem_A</item>
      </item>
    <item>Item_B</item>
  </item>
</root>

XSLT 1.0样式表

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

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

<xsl:template match="item">
  <xsl:number level="multiple" format="1. "/>
  <xsl:apply-templates match="item"/>
</xsl:template>

</xsl:stylesheet>

HTML输出

<html>
  <body>
  1. Main_A
    1.1. Item_A
    1.2. Item_B
      1.2.1. Subitem_A
      1.2.2. Subitem_B

    1.3. Item_C

  2. Main_B
    2.1. Item_A
      2.1.1. Subitem_A

    2.2. Item_B

</body>
</html>

2 个答案:

答案 0 :(得分:1)

我认为你需要转移到XSLT 3.0并使用https://www.w3.org/TR/xslt-30/#start-at例如

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:math="http://www.w3.org/2005/xpath-functions/math"
    exclude-result-prefixes="xs math"
    version="3.0">

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

    <xsl:template match="item">
        <xsl:number level="multiple" format="1. " start-at="0"/>
        <xsl:apply-templates/>
    </xsl:template>

</xsl:stylesheet>

使用oXygen 19和Saxon 9.7 PE给出结果

<html>
   <body>
        0. Main_A
            0.0. Item_A
            0.1. Item_B
                0.1.0. Subitem_A
                0.1.1. Subitem_B

            0.2. Item_C

        1. Main_B
            1.0. Item_A
                1.0.0. Subitem_A

            1.1. Item_B


   </body>
</html>

输入样本。

答案 1 :(得分:1)

如果您的处理器支持EXSLT str:tokenize()扩展功能(我相信它),您可以这样做:

XSLT 1.0

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">

<xsl:template match="/root">
    <html>
        <body>
            <ul>
                <xsl:apply-templates select="item"/>
            </ul>
        </body>
    </html>
</xsl:template>

<xsl:template match="item">
    <xsl:variable name="num">
        <xsl:number level="multiple" format="1."/>
    </xsl:variable>
    <li>
        <xsl:text>path:</xsl:text>
        <xsl:for-each select="str:tokenize($num, '.')">         
            <xsl:value-of select=". - 1" />
            <xsl:if test="position()!=last()">
                <xsl:text>:</xsl:text>
            </xsl:if>
        </xsl:for-each>
        <xsl:text> = </xsl:text>
        <xsl:value-of select="text()" />
        <xsl:if test="item">
            <ul>
                <xsl:apply-templates select="item"/>
            </ul>
        </xsl:if>
    </li>
</xsl:template>

</xsl:stylesheet>

应用于您的输入示例,结果将是:

<html>
<body>
<ul>
<li>path:0 = Main_A
    <ul>
<li>path:0:0 = Item_A</li>
<li>path:0:1 = Item_B
      <ul>
<li>path:0:1:0 = Subitem_A</li>
<li>path:0:1:1 = Subitem_B</li>
</ul>
</li>
<li>path:0:2 = Item_C</li>
</ul>
</li>
<li>path:1 = Main_B
    <ul>
<li>path:1:0 = Item_A
      <ul>
<li>path:1:0:0 = Subitem_A</li>
</ul>
</li>
<li>path:1:1 = Item_B</li>
</ul>
</li>
</ul>
</body>
</html>

呈现为:

enter image description here

我认为这是您在your other question中要求的结果。

请注意,match不是xsl:apply-templates的有效属性。