首页 文章

XSLT 2.0中每个组的全局序列编号

提问于
浏览
0

我必须生成一个xml文件,其中某些分组元素(分组行的文档)用序列编号 . 反过来,这些组属于另一组(按文档类型) . 无论组如何,编号在所有文档中都必须是连续的 .

请参阅示例输出中Documents元素中的属性 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(),这对我来说适用于有限数量的组,但是对于可变数量的组,它不能一般地进行 .

是否有一些相对简单的方法来实现这一目标?先感谢您 .

1 回答

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

相关问题