在XSLT中创建序列号

8

输入XML:

<doc>
 <section>
  <para>Paragraph 1</para>
  <para>Paragraph 2</para>
  <para>Paragraph 3</para>
 </section>
  <para>Paragraph 4</para>
  <para>Paragraph 5</para>
  <para>Paragraph 6</para>
</doc>

需要的输出:

<book>
<section>
  <p class="para" id="0001">Paragraph 1</p>
  <p class="para" id="0002">Paragraph 2</p>
  <p class="para" id="0003">Paragraph 3</p>
 </section>
  <p class="para" id="0004">Paragraph 4</p>
  <p class="para" id="0005">Paragraph 5</p>
  <p class="para" id="0006">Paragraph 6</p>
 </book>

我尝试使用以下XSL,但我没有得到想要的输出。有人可以帮忙吗?
<xsl:template match="para">
    <xsl:variable name="count" select="position()"/>
    <p class="para" id="{$count}">
        <xsl:apply-templates/>
    </p>
</xsl:template>

我得到的结果是:
<p class="para" id="2">Paragraph 1</p>
<p class="para" id="4">Paragraph 2</p>
<p class="para" id="6">Paragraph 3</p>

    <p class="para" id="4">Paragraph 4</p>
    <p class="para" id="6">Paragraph 5</p>
    <p class="para" id="8">Paragraph 6</p>

你能理解这个吗?<p class="para" id="4">第4段</p> - vels4j
不,我得到的结果是:

段落1

段落2

段落3

段落4

段落5

段落6

- VSe
请通过编辑您的问题展示您的输出XML。 - Jim Garrison
2个回答

16
这里有一个选项,不使用xsl:for-each或任何xsl:variable...。
<doc>
    <section>
        <para>Paragraph 1</para>
        <para>Paragraph 2</para>
        <para>Paragraph 3</para>
    </section>
    <para>Paragraph 4</para>
    <para>Paragraph 5</para>
    <para>Paragraph 6</para>
</doc>

XSLT 1.0

<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="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

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

    <xsl:template match="para">
        <p class="para" id="{format-number(count(preceding::para)+1,'0000')}">
            <xsl:apply-templates select="@*|node()"/>
        </p>
    </xsl:template>

</xsl:stylesheet>

XML输出

<book>
   <section>
      <p class="para" id="0001">Paragraph 1</p>
      <p class="para" id="0002">Paragraph 2</p>
      <p class="para" id="0003">Paragraph 3</p>
   </section>
   <p class="para" id="0004">Paragraph 4</p>
   <p class="para" id="0005">Paragraph 5</p>
   <p class="para" id="0006">Paragraph 6</p>
</book>
第二个选项是,不需要计算 preceding::para ,您可以使用 xsl:number...
<xsl:template match="para">
    <p class="para">
        <xsl:attribute name="id">
            <xsl:number format="0000" level="any"/>
        </xsl:attribute>
        <xsl:apply-templates select="@*|node()"/>
    </p>
</xsl:template>

我做到了。如果有人反对一个赞成,你会得到9个(10-2)。 :-) - vels4j
@DimitreNovatchev - 谢谢。我也很喜欢你关于单词阶梯的博客文章。非常有趣! - Daniel Haley
@DevNull,欢迎您的到来。非常抱歉博客文章中代码格式混乱 - 目前我还没有找到一种方法来使WordPress正确地格式化XML / XSLT代码。 - Dimitre Novatchev

2

这是您需要的XSL文件

 <xsl:template match="doc">
    <book>
        <section>
            <xsl:for-each select="section/para">
                <xsl:variable name="count" select="position()"/>
                <xsl:variable name ="seq">
                    <xsl:value-of select="format-number($count,'0000')"/>
                </xsl:variable>
                <p class="para" id="{$seq}">
                    <xsl:value-of select="."/>
                </p>
            </xsl:for-each>
        </section>
        <xsl:variable name="secCount" select="count(section/para)"/>
        <xsl:for-each select="para">
            <xsl:variable name="count" select="position()"/>
            <xsl:variable name ="seq">
            <xsl:value-of select="format-number( number($count) + number($secCount),'0000')"/>
        </xsl:variable>
            <p class="para" id="{$seq}">
                <xsl:value-of select="."/>
            </p>
        </xsl:for-each>
    </book>
</xsl:template>

专家们可能仍然可以简化这个XSL。我已经尽力了解到的程度。 - vels4j
如果有多个 section 或者 section 不总是在同级的 para 前面,那样做效果不太好。 - Daniel Haley

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接