XSLT 2,按属性和元素进行多重分组

XSLT 2, Mutiple grouping by attributes and elements

我似乎无法根据婚姻状况对夫妇进行分组。
我设法将所有处于恋爱关系中的人分组 ('DeFacto', 'Married'),但无法弄清楚如何将他们分组到不同的家庭中。

基本上,如果两个人组成一对,他们就会创建一个家庭。户名将属于家庭中的第一人姓氏,NumberOfAdults 将被硬编码为“2”并且 NumberOfDependants 将被求和。

这对情侣是根据 Party.Identifier 和 Party.MaritalStatus.RelatedEntityRef

建立联系的

我有什么(简体):

<PartySegment>
<Party Type="Guarantor" PrimaryApplicant="No">
    <Identifier>b8b0f908b08e</Identifier>
    <Person Sex="Female" FirstHomeBuyer="No" CustomerOfLender="No">
        <PersonName>
            <NameTitle Value="Lady"/>
            <FirstName>Clemansa</FirstName>
            <Surname>Sanchez</Surname>
        </PersonName>
        <MaritalStatus Status="DeFacto">
            <RelatedEntityRef>ea384b0bf3f5</RelatedEntityRef>
        </MaritalStatus>
        <NumberOfDependents>1</NumberOfDependents>
    </Person>
</Party>
<Party Type="Applicant" PrimaryApplicant="Yes" ExistingCustomerID="1231">
    <Identifier>bd8c65a3ad80</Identifier>
    <Person Sex="Female" FirstHomeBuyer="Yes" CustomerOfLender="Yes">
        <PersonName>
            <NameTitle Value="Mrs"/>
            <FirstName>Cheryl</FirstName>
            <Surname>Bonkers</Surname>
        </PersonName>
        <MaritalStatus Status="Married">
            <RelatedEntityRef>ee84dc9e38ec</RelatedEntityRef>
        </MaritalStatus>
        <NumberOfDependents>2</NumberOfDependents>
    </Person>
</Party>
<Party Type="Guarantor" PrimaryApplicant="No">
    <Identifier>ea384b0bf3f5</Identifier>
    <Person Sex="Male" FirstHomeBuyer="No" CustomerOfLender="No">
        <PersonName>
            <NameTitle Value="Mr"/>
            <FirstName>Greg</FirstName>
            <OtherName>Morty</OtherName>
            <Surname>Sanchez</Surname>
        </PersonName>
        <MaritalStatus Status="DeFacto">
            <RelatedEntityRef>b8b0f908b08e</RelatedEntityRef>
        </MaritalStatus>
        <NumberOfDependents>0</NumberOfDependents>
    </Person>
</Party>
<Party Type="Applicant" PrimaryApplicant="No">
    <Identifier>ee84dc9e38ec</Identifier>
    <Person Sex="Male" FirstHomeBuyer="No" CustomerOfLender="No">
        <PersonName>
            <NameTitle Value="Mr"/>
            <FirstName>Mark</FirstName>
            <Surname>Bonkers</Surname>
        </PersonName>
        <MaritalStatus Status="Married">
            <RelatedEntityRef>bd8c65a3ad80</RelatedEntityRef>
        </MaritalStatus>
        <NumberOfDependents>0</NumberOfDependents>
    </Person>
</Party>
</PartySegment>

愿望输出:

<Household UniqueID="b8b0f908b08e-Household"
                Name="Sanchez Household"
                NumberOfAdults="2"
                NumberOfDependants="1"/>

<Household UniqueID="bd8c65a3ad80-Household"
                Name="Bonkers Household"
                NumberOfAdults="2"
                NumberOfDependants="2"/>

到目前为止我所知道的(简化):这适用于一对夫妇,因为没有考虑 MaritalStatus.RelatedEntityRef 信息

<xsl:template match="PartySegment" mode="Household_Couple">

    <xsl:for-each-group select="Party[Person/MaritalStatus/@Status = ('DeFacto', 'Married')]" group-by="Person/MaritalStatus/@Status = ('DeFacto', 'Married')">
        <xsl:variable name="owner_id" select="Identifier"/>

        <Household UniqueID="{concat(Identifier, '-Household')}" 
            Name="{normalize-space(concat(Person/PersonName/Surname, ' Household'))}"
            NumberOfAdults="{'2'}"
            NumberOfDependants="{if(Person/Dependent) then count(current-group()/Person/Dependent) else if(Person/NumberOfDependents) then sum(current-group()/Person/NumberOfDependents) else '0'}">

            <xsl:apply-templates select="current-group()/Person/Dependent"/>

        </Household>
    </xsl:for-each-group>
</xsl:template>

如果您可以迁移到 XSLT 3.0,那么我认为两个相关标识符的复合分组键 sort((Identifier, key('ref', Person/MaritalStatus/RelatedEntityRef)/Identifier)) 可以解决这个问题:

<xsl:key name="ref" match="Party" use="Identifier"/>

<xsl:template match="PartySegment">
    <xsl:for-each-group select="Party[Person/MaritalStatus/@Status = ('DeFacto', 'Married')]" 
        composite="yes" 
        group-by="sort((Identifier, key('ref', Person/MaritalStatus/RelatedEntityRef)/Identifier))">
        <Household UniqueID="{concat(Identifier, '-Household')}" 
            Name="{normalize-space(concat(Person/PersonName/Surname, ' Household'))}"
            NumberOfAdults="{'2'}"
            NumberOfDependants="{if(Person/Dependent) then count(current-group()/Person/Dependent) else if(Person/NumberOfDependents) then sum(current-group()/Person/NumberOfDependents) else '0'}">



        </Household>
    </xsl:for-each-group>
</xsl:template>

我明白了

<Household UniqueID="b8b0f908b08e-Household"
           Name="Sanchez Household"
           NumberOfAdults="2"
           NumberOfDependants="1"/>
<Household UniqueID="bd8c65a3ad80-Household"
           Name="Bonkers Household"
           NumberOfAdults="2"
           NumberOfDependants="2"/>

这样在 oXygen 中使用 Saxon 9.8 EE。

对于 Saxon 9.8 HE,应该可以将其重写为

<xsl:key name="ref" match="Party" use="Identifier"/>

<xsl:template match="PartySegment">
    <xsl:for-each-group select="Party[Person/MaritalStatus/@Status = ('DeFacto', 'Married')]" 
        composite="yes" 
        group-by="Identifier | key('ref', Person/MaritalStatus/RelatedEntityRef)/Identifier">
        <Household UniqueID="{concat(Identifier, '-Household')}" 
            Name="{normalize-space(concat(Person/PersonName/Surname, ' Household'))}"
            NumberOfAdults="{'2'}"
            NumberOfDependants="{if(Person/Dependent) then count(current-group()/Person/Dependent) else if(Person/NumberOfDependents) then sum(current-group()/Person/NumberOfDependents) else '0'}">



        </Household>
    </xsl:for-each-group>
</xsl:template>

对于没有复合键的 XSLT 2.0,我们需要确保使用两个组件构建一个键:

<xsl:template match="PartySegment">
    <xsl:for-each-group select="Party[Person/MaritalStatus/@Status = ('DeFacto', 'Married')]" 
        group-by="string-join((Identifier | key('ref', Person/MaritalStatus/RelatedEntityRef)/Identifier), '|')">
        <Household UniqueID="{concat(Identifier, '-Household')}" 
            Name="{normalize-space(concat(Person/PersonName/Surname, ' Household'))}"
            NumberOfAdults="{'2'}"
            NumberOfDependants="{if(Person/Dependent) then count(current-group()/Person/Dependent) else if(Person/NumberOfDependents) then sum(current-group()/Person/NumberOfDependents) else '0'}">



        </Household>
    </xsl:for-each-group>
</xsl:template>