生成顺序行号。或者在XSLT 2.0中使用计数器

时间:2013-06-18 20:49:26

标签: xslt xpath

我的示例输入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>

1 个答案:

答案 0 :(得分:0)

如果您真的想要创建for-each-group元素,我认为您可以使用<xsl:element name="Accounts{position()}">...</xsl:element>AccountsX。要使用category元素顺序对llNo元素进行编号,我认为您首先需要将变量分组,然后才能使用<xsl:number level="any"/>

因此,采用这种方法的样式表是

<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>
<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>

进入结果

<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>

另一方面,将索引号放入元素名称(如Accounts1Accounts2)是糟糕的XML设计,您永远无法为此编写架构。