2017-10-13 175 views
0

我必须生成一个xml文件,其中某些分组元素(文档中的哪些组行)用一个序列编号。反过来,这些组属于另一组(按文档类型)。编号必须在所有文档中连续进行,无论组是什么。XSLT 2.0中每个组的跨越不同的全局序列编号

参见在实施例输出的文档元素的属性的DocID

INPUT

<Entries> 
    <Entry> 
     <UserID>1</UserID> 
     <DocNumber>1002</DocNumber> 
     <Description>An invoice</Description> 
     <Amount>3103.2000</Amount> 
     <DocType>INVOICE</DocType> 
    </Entry> 
    <Entry> 
     <UserID>2</UserID> 
     <DocNumber>3001</DocNumber> 
     <Description>Some receipt</Description> 
     <Amount>2352.0000</Amount> 
     <DocType>RECEIPT</DocType> 
    </Entry> 
    <Entry> 
     <UserID>1</UserID> 
     <DocNumber>1002</DocNumber> 
     <Description>An invoice</Description> 
     <Amount>2861.8400</Amount> 
     <DocType>INVOICE</DocType> 
    </Entry> 
    <Entry> 
     <UserID>2</UserID> 
     <DocNumber>3001</DocNumber> 
     <Description>Some receipt</Description> 
     <Amount>2352.0000</Amount> 
     <DocType>RECEIPT</DocType> 
    </Entry> 
    <Entry> 
     <UserID>5</UserID> 
     <DocNumber>1004</DocNumber> 
     <Description>Another invoice</Description> 
     <Amount>2.34</Amount> 
     <DocType>INVOICE</DocType> 
    </Entry> 
</Entries> 

XSLT 2.0

<xsl:stylesheet exclude-result-prefixes="xs xdt err fn" version="2.0" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ser="http://webservice"> 
    <xsl:output indent="yes" method="xml"/> 
    <xsl:template match="/Entries"> 
     <ser:Request> 
       <xsl:for-each-group select="Entry" group-by="DocType"> 
        <xsl:sort select="current-grouping-key()"/>      
        <ser:ItemFile ImportName="{DocType}" Date="{current-date()}"> 
         <xsl:for-each-group select="current-group()" group-by="DocNumber"> 
          <xsl:sort select="current-grouping-key()"/>        
          <ser:Documents DocId="{position()}" DocRef="{DocNumber}" Desc="{Description}" > 
           <xsl:for-each select="current-group()"> 
            <Line amount="{Amount}"/> 
           </xsl:for-each> 
          </ser:Documents> 
         </xsl:for-each-group> 
        </ser:ItemFile> 
       </xsl:for-each-group> 
     </ser:Request> 
    </xsl:template> 
</xsl:stylesheet> 

OUTPUT

<ser:Request xmlns:ser="http://webservice"> 
    <ser:ItemFile ImportName="INVOICE" Date="2017-10-13+02:00"> 
     <ser:Documents DocId="1" DocRef="1002" Desc="An invoice"> 
     <Line amount="3103.2000"/> 
     <Line amount="2861.8400"/> 
     </ser:Documents> 
     <ser:Documents DocId="2" DocRef="1004" Desc="Another invoice"> 
     <Line amount="2.34"/> 
     </ser:Documents> 
    </ser:ItemFile> 
    <ser:ItemFile ImportName="RECEIPT" Date="2017-10-13+02:00"> 
     <ser:Documents DocId="1" DocRef="3001" Desc="Some receipt"> 
     <Line amount="2352.0000"/> 
     <Line amount="2352.0000"/> 
     </ser:Documents> 
    </ser:ItemFile> 
</ser:Request> 

在此示例中,根据序列,最后一个DocId属性的所需输出为3。

我注意到如果我使用position()函数,编号会在每个组中重新启动,这不是我想要的。我也尝试过xsl:number元素,但没有成功。我考虑计算第一组中的元素并将其添加到position()中,这对于有限数量的组适用于我,但对于可变数量的组无法实现。

是否有一些相对简单的方法来实现这一点?先谢谢你。

回答

0

我会存储在一个变量新创建的元素,然后将其推通过复制的一切,但该DocId属性模板,然后可在使用xsl:number设置它:

<xsl:stylesheet exclude-result-prefixes="xs xdt err fn" version="2.0" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xdt="http://www.w3.org/2005/xpath-datatypes" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ser="http://webservice"> 
    <xsl:output indent="yes" method="xml"/> 

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

    <xsl:template match="/Entries"> 
     <ser:Request> 
      <xsl:variable name="result"> 
       <xsl:for-each-group select="Entry" group-by="DocType"> 
        <xsl:sort select="current-grouping-key()"/>      
        <ser:ItemFile ImportName="{DocType}" Date="{current-date()}"> 
         <xsl:for-each-group select="current-group()" group-by="DocNumber"> 
          <xsl:sort select="current-grouping-key()"/>        
          <ser:Documents DocId="" DocRef="{DocNumber}" Desc="{Description}" > 
           <xsl:for-each select="current-group()"> 
            <Line amount="{Amount}"/> 
           </xsl:for-each> 
          </ser:Documents> 
         </xsl:for-each-group> 
        </ser:ItemFile> 
       </xsl:for-each-group>   
      </xsl:variable> 
      <xsl:apply-templates select="$result"/> 
     </ser:Request> 
    </xsl:template> 

    <xsl:template match="ser:Documents/@DocId"> 
     <xsl:attribute name="{name()}"> 
      <xsl:number select=".." level="any"/> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 
+0

这只是工作,非常感谢 – user8658912