在XSLT 2.0中生成顺序行号或计数器

在XSLT 2.0中生成顺序行号或计数器,xslt,xpath,Xslt,Xpath,我的示例输入XML如下所示。我需要按顺序生成llNo元素,同时根据code元素值对元素进行分组 <voucher> <ID>1234</ID> <Type>Voucher</Type> <Flag>true</Flag> <Accounts> <AccId>89</AccId> <AccCd1>a11</AccCd1>

我的示例输入XML如下所示。我需要按顺序生成
llNo
元素,同时根据
code
元素值对元素进行分组

<voucher>
<ID>1234</ID>
<Type>Voucher</Type>
<Flag>true</Flag>
<Accounts>
    <AccId>89</AccId>
    <AccCd1>a11</AccCd1>        
    <category>
        <catId>ct11</catId>
        <code>IB</code>
        <Details>abcd</Details>         
    </category>
    <category>
        <catId>ct12</catId>
        <code>IB</code>
        <Details>cvbn</Details>         
    </category>
    <category>
        <catId>ct13</catId>
        <code>CB</code>
        <Details>asdfg</Details>            
    </category>
    <category>
        <catId>ct14</catId>
        <code>TV</code>
        <Details>asdfg</Details>            
    </category>
</Accounts>
<Accounts>
    <AccId>89</AccId>
    <AccCd1>a11</AccCd1>        
    <category>
        <catId>ct15</catId>
        <code>IB</code>
        <Details>abcd</Details>         
    </category>
    <category>
        <catId>ct16</catId>
        <code>CB</code>
        <Details>cvbn</Details>         
    </category>
    <category>
        <catId>ct17</catId>
        <code>CB</code>
        <Details>asdfg</Details>            
    </category>
    <category>
        <catId>ct18</catId>
        <code>TV</code>
        <Details>asdfg</Details>

    </category>
</Accounts>
</voucher>
输出XML应采用以下格式

<Voucher>
<ID>1234</ID>
<Type>Voucher</Type>
<Flag>true</Flag>
<Accounts1>
    <AccId>89</AccId>
    <AccCd1>a11</AccCd1>    
    <category>
        <llNo>1</llNo>
        <catId>ct11</catId>
        <code>IB</code>
        <Details>abcd</Details>         
    </category>
    <category>
        <llNo>2</llNo>
        <catId>ct12</catId>
        <code>IB</code>
        <Details>cvbn</Details>         
    </category>
    <category>
        <llNo>3</llNo>
        <catId>ct15</catId>
        <code>IB</code>
        <Details>abcd</Details>         
    </category>
</Accounts1>
<Accounts2>
    <AccId>89</AccId>
    <AccCd1>a11</AccCd1>
    <category>
        <llNo>4</llNo>
        <catId>ct13</catId>
        <code>CB</code>
        <Details>asdfg</Details>            
    </category>
    <category>
        <llNo>5</llNo>
        <catId>ct17</catId>
        <code>CB</code>
        <Details>asdfg</Details>            
    </category>
<Accounts2>
<Accounts3>
    <AccId>89</AccId>
    <AccCd1>a11</AccCd1>
    <category>
        <llNo>6</llNo>
        <catId>ct14</catId>
        <code>TV</code>
        <Details>asdfg</Details>            
    </category>
    <category>
        <llNo>7</llNo>
        <catId>ct18</catId>
        <code>TV</code>
        <Details>asdfg</Details>

    </category>
<Accounts3>
</Voucher>

我认为如果您真的想创建
AccountsX
元素,可以对每个组使用
..
。要用
llNo
元素按顺序对
category
元素进行编号,我认为首先需要将其分组为一个变量,然后可以使用

因此,通过这种方法,样式表是

<xsl:stylesheet version="2.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="voucher">
  <Voucher>
    <xsl:apply-templates select="* except Accounts"/>
    <xsl:variable name="groups">
      <xsl:for-each-group select="Accounts/category" group-by="code">
        <xsl:element name="Accounts{position()}">
          <xsl:copy-of select="../(AccId, AccCd1), current-group()"/>
        </xsl:element>
      </xsl:for-each-group>
    </xsl:variable>
    <xsl:apply-templates select="$groups/*"/>
  </Voucher>
</xsl:template>

<xsl:template match="category">
  <xsl:copy>
    <llNo><xsl:number level="any"/></llNo>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

</xsl:stylesheet>
结果如何

<Voucher>
   <ID>1234</ID>
   <Type>Voucher</Type>
   <Flag>true</Flag>
   <Accounts1>
      <AccId>89</AccId>
      <AccCd1>a11</AccCd1>
      <category>
         <llNo>1</llNo>
         <catId>ct11</catId>
         <code>IB</code>
         <Details>abcd</Details>
      </category>
      <category>
         <llNo>2</llNo>
         <catId>ct12</catId>
         <code>IB</code>
         <Details>cvbn</Details>
      </category>
      <category>
         <llNo>3</llNo>
         <catId>ct15</catId>
         <code>IB</code>
         <Details>abcd</Details>
      </category>
   </Accounts1>
   <Accounts2>
      <AccId>89</AccId>
      <AccCd1>a11</AccCd1>
      <category>
         <llNo>4</llNo>
         <catId>ct13</catId>
         <code>CB</code>
         <Details>asdfg</Details>
      </category>
      <category>
         <llNo>5</llNo>
         <catId>ct16</catId>
         <code>CB</code>
         <Details>cvbn</Details>
      </category>
      <category>
         <llNo>6</llNo>
         <catId>ct17</catId>
         <code>CB</code>
         <Details>asdfg</Details>
      </category>
   </Accounts2>
   <Accounts3>
      <AccId>89</AccId>
      <AccCd1>a11</AccCd1>
      <category>
         <llNo>7</llNo>
         <catId>ct14</catId>
         <code>TV</code>
         <Details>asdfg</Details>
      </category>
      <category>
         <llNo>8</llNo>
         <catId>ct18</catId>
         <code>TV</code>
         <Details>asdfg</Details>
      </category>
   </Accounts3>
</Voucher>

另一方面,将索引号放入元素名称中,如
Accounts1
Accounts2
,是糟糕的XML设计,您永远无法为此编写模式。

您尝试了什么,在哪里遇到了问题?对于每个组和位置(),使用XSLT2.0非常简单。
<Voucher>
   <ID>1234</ID>
   <Type>Voucher</Type>
   <Flag>true</Flag>
   <Accounts1>
      <AccId>89</AccId>
      <AccCd1>a11</AccCd1>
      <category>
         <llNo>1</llNo>
         <catId>ct11</catId>
         <code>IB</code>
         <Details>abcd</Details>
      </category>
      <category>
         <llNo>2</llNo>
         <catId>ct12</catId>
         <code>IB</code>
         <Details>cvbn</Details>
      </category>
      <category>
         <llNo>3</llNo>
         <catId>ct15</catId>
         <code>IB</code>
         <Details>abcd</Details>
      </category>
   </Accounts1>
   <Accounts2>
      <AccId>89</AccId>
      <AccCd1>a11</AccCd1>
      <category>
         <llNo>4</llNo>
         <catId>ct13</catId>
         <code>CB</code>
         <Details>asdfg</Details>
      </category>
      <category>
         <llNo>5</llNo>
         <catId>ct16</catId>
         <code>CB</code>
         <Details>cvbn</Details>
      </category>
      <category>
         <llNo>6</llNo>
         <catId>ct17</catId>
         <code>CB</code>
         <Details>asdfg</Details>
      </category>
   </Accounts2>
   <Accounts3>
      <AccId>89</AccId>
      <AccCd1>a11</AccCd1>
      <category>
         <llNo>7</llNo>
         <catId>ct14</catId>
         <code>TV</code>
         <Details>asdfg</Details>
      </category>
      <category>
         <llNo>8</llNo>
         <catId>ct18</catId>
         <code>TV</code>
         <Details>asdfg</Details>
      </category>
   </Accounts3>
</Voucher>