简体   繁体   English

XSLT 2.0中每个组的全局序列号各不相同

[英]global sequence numbering across different for each groups in XSLT 2.0

I have to generate an xml file where certain grouped elements (documents which group lines) are numbered with a sequence. 我必须生成一个xml文件,其中某些分组的元素(分组行的文档)按顺序编号。 In turn, these groups belong within another group (by document type). 这些组又属于另一个组(按文档类型)。 The numbering must be sequential during all the document, regardless of the group. 无论在哪个组中,在所有文档中编号都必须是连续的。

See the attribute DocId in the Documents element in the example output: 请参阅示例输出中的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 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>

In this example, the desired output for last DocId attribute would be 3, following the sequence. 在此示例中,最后一个DocId属性的期望输出将为3,遵循该顺序。

I noticed if I use the position() function, the numbering restarts in each group, which is not what I want. 我注意到如果我使用position()函数,则会在每个组中重新开始编号,这不是我想要的。 I also tried the xsl:number element with no success. 我也尝试了xsl:number元素,但没有成功。 I considered counting the elements in the first group and adding it to position(), which worked for me for a limited number of groups, but couldn't do it generically for a variable number of groups. 我考虑过对第一组中的元素进行计数,然后将其添加到position()中,这对我有限的组有效,但对于可变数量的组却无法通用。

Is there some relatively simple way of achieving this? 是否有一些相对简单的方法来实现这一目标? Thank you in advance. 先感谢您。

I would store the newly created elements in a variable and then push it through templates that copy everything but that DocId attribute where you can then use xsl:number to set it: 我会将新创建的元素存储在变量中,然后将其推送通过模板,该模板复制除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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM