Grouping flat xml using xslt (muenchian grouping), can't get it to group

冷暖自知 提交于 2019-12-02 08:19:49

Well, given that you know the item you want to group by it should not be that difficult to define your key <xsl:key name="group" match="fmp:ROW" use="fmp:COL[12]/fmp:DATA"/> and use it:

<xsl:key name="group" match="fmp:ROW" use="fmp:COL[12]/fmp:DATA"/>

<xsl:output method="xml" indent="yes"/>

<xsl:template match="/fmp:FMPXMLRESULT">
    <Invoices>
        <xsl:apply-templates
            select="fmp:RESULTSET/fmp:ROW[generate-id() = generate-id(key('group', fmp:COL[12]/fmp:DATA)[1])]"
        />
    </Invoices>
</xsl:template>

<xsl:template match="fmp:RESULTSET/fmp:ROW">
    <Invoice>
        <Recipient>
            <MemberNo>
                <xsl:apply-templates select="fmp:COL[1]"/>
            </MemberNo>
            <CheckDigit>
                <xsl:apply-templates select="fmp:COL[2]"/>
            </CheckDigit>
            <FirstName>
                <xsl:apply-templates select="fmp:COL[3]"/>
            </FirstName>
            <LastName>
                <xsl:apply-templates select="fmp:COL[4]"/>
            </LastName>
            <GuardianFirstName>
                <xsl:apply-templates select="fmp:COL[5]"/>
            </GuardianFirstName>
            <GuardianLastName>
                <xsl:apply-templates select="fmp:COL[6]"/>
            </GuardianLastName>
            <Address1>
                <xsl:apply-templates select="fmp:COL[7]"/>
            </Address1>
            <Address2>
                <xsl:apply-templates select="fmp:COL[8]"/>
            </Address2>
            <PostalCode>
                <xsl:apply-templates select="fmp:COL[9]"/>
            </PostalCode>
            <City>
                <xsl:apply-templates select="fmp:COL[10]"/>
            </City>
            <State>
                <xsl:apply-templates select="fmp:COL[11]"/>
            </State>
        </Recipient>
        <InvoiceHeader>
            <OrderNo>
                <xsl:apply-templates select="fmp:COL[13]"/>
            </OrderNo>
            <Postage>
                <xsl:apply-templates select="fmp:COL[14]"/>
            </Postage>
            <OrderTotal>
                <xsl:apply-templates select="fmp:COL[15]"/>
            </OrderTotal>
            <Discount>
                <xsl:apply-templates select="fmp:COL[16]"/>
            </Discount>
            <VATAmount>
                <xsl:apply-templates select="fmp:COL[17]"/>
            </VATAmount>
            <AmountToPay>
                <xsl:apply-templates select="fmp:COL[18]"/>
            </AmountToPay>
            <PaymentReferenceNo>
                <xsl:apply-templates select="fmp:COL[19]"/>
            </PaymentReferenceNo>
            <AmountModus>
                <xsl:apply-templates select="fmp:COL[20]"/>
            </AmountModus>
        </InvoiceHeader>
        <InvoiceLines>
            <xsl:for-each select="key('group', fmp:COL[12]/fmp:DATA)">
                <InvoiceLine>
                    <LineNo>
                        <xsl:apply-templates select="fmp:COL[21]"/>
                    </LineNo>
                    <LineType>
                        <xsl:apply-templates select="fmp:COL[22]"/>
                    </LineType>
                    <ItemNo>
                        <xsl:apply-templates select="fmp:COL[23]"/>
                    </ItemNo>
                    <ItemDescription>
                        <xsl:apply-templates select="fmp:COL[24]"/>
                    </ItemDescription>
                    <Quantity>
                        <xsl:apply-templates select="fmp:COL[25]"/>
                    </Quantity>
                    <UnitPrice>
                        <xsl:apply-templates select="fmp:COL[26]"/>
                    </UnitPrice>
                    <LineAmount>
                        <xsl:apply-templates select="fmp:COL[27]"/>
                    </LineAmount>
                </InvoiceLine>
            </xsl:for-each>
        </InvoiceLines>
    </Invoice>
</xsl:template>

<xsl:template match="fmp:COL">
    <xsl:value-of select="fmp:DATA"/>
</xsl:template>

I reused your code (had to increment some positional predicates), I would consider cleaning up all those <xsl:apply-templates select="fmp:COL[N]"/> to simply use <xsl:value-of select="fmp:COL[N]/fmp:DATA"/> however, as in this case the pushing the processing to a template does not really achieve some transformation.

You don't need to use Muenchian grouping if you're doing the XSL transformation while exporting from FileMaker. You can take advantage of the EXSLT set:distinct() extension function that FileMaker's XSLT engine supports:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fmp="http://www.filemaker.com/fmpxmlresult" 
xmlns:set="http://exslt.org/sets"
exclude-result-prefixes="fmp set">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:key name="group" match="fmp:ROW" use="fmp:COL[12]/fmp:DATA" />

<xsl:template match="/fmp:FMPXMLRESULT">
    <Invoices>
        <xsl:for-each select="set:distinct(fmp:RESULTSET/fmp:ROW/fmp:COL[12]/fmp:DATA)">
            <Invoice>
                <Recipient>
                    <MemberNo>
                        <xsl:value-of select="../../fmp:COL[1]/fmp:DATA" />
                    </MemberNo>
                    <CheckDigit>
                        <xsl:value-of select="../../fmp:COL[2]/fmp:DATA" />
                    </CheckDigit>
                    <FirstName>
                        <xsl:value-of select="../../fmp:COL[3]/fmp:DATA" />
                    </FirstName>
                    <LastName>
                        <xsl:value-of select="../../fmp:COL[4]/fmp:DATA" />
                    </LastName>
                    <GuardianFirstName>
                        <xsl:value-of select="../../fmp:COL[5]/fmp:DATA" />
                    </GuardianFirstName>
                    <GuardianLastName>
                        <xsl:value-of select="../../fmp:COL[6]/fmp:DATA" />
                    </GuardianLastName>
                    <Address1>
                        <xsl:value-of select="../../fmp:COL[7]/fmp:DATA" />
                    </Address1>
                    <Address2>
                        <xsl:value-of select="../../fmp:COL[8]/fmp:DATA" />
                    </Address2>
                    <PostalCode>
                        <xsl:value-of select="../../fmp:COL[9]/fmp:DATA" />
                    </PostalCode>
                    <City>
                        <xsl:value-of select="../../fmp:COL[10]/fmp:DATA" />
                    </City>
                    <State>
                        <xsl:value-of select="../../fmp:COL[11]/fmp:DATA" />
                    </State>
                </Recipient>
               <InvoiceHeader>
                    <OrderNo>
                        <xsl:value-of select="../../fmp:COL[12]/fmp:DATA" />
                    </OrderNo>              
                    <Postage>
                        <xsl:value-of select="../../fmp:COL[13]/fmp:DATA" />
                    </Postage>
                    <OrderTotal>
                        <xsl:value-of select="../../fmp:COL[14]/fmp:DATA" />
                    </OrderTotal>
                    <Discount>
                        <xsl:value-of select="../../fmp:COL[15]/fmp:DATA" />
                    </Discount>
                    <VATAmount>
                        <xsl:value-of select="../../fmp:COL[16]/fmp:DATA" />
                    </VATAmount>
                    <AmountToPay>
                        <xsl:value-of select="../../fmp:COL[17]/fmp:DATA" />
                    </AmountToPay>
                    <PaymentReferenceNo>
                        <xsl:value-of select="../../fmp:COL[18]/fmp:DATA" />
                    </PaymentReferenceNo>
                    <AmountModus>
                        <xsl:value-of select="../../fmp:COL[19]/fmp:DATA" />
                    </AmountModus>
                </InvoiceHeader>        
                <InvoiceLines>
                    <xsl:for-each select="key('group', .)" >
                       <InvoiceLine>
                            <LineNo>
                                <xsl:value-of select="fmp:COL[20]/fmp:DATA" />
                            </LineNo>
                            <LineType>
                                <xsl:value-of select="fmp:COL[21]/fmp:DATA" />
                            </LineType>
                            <ItemNo>
                                <xsl:value-of select="fmp:COL[22]/fmp:DATA" />
                            </ItemNo>
                            <ItemDescription>
                                <xsl:value-of select="fmp:COL[23]/fmp:DATA" />
                            </ItemDescription>
                            <Quantity>
                                <xsl:value-of select="fmp:COL[24]/fmp:DATA" />
                            </Quantity>
                            <UnitPrice>
                                <xsl:value-of select="fmp:COL[25]/fmp:DATA" />
                            </UnitPrice>
                            <LineAmount>
                                <xsl:value-of select="fmp:COL[26]/fmp:DATA" />
                            </LineAmount>
                        </InvoiceLine>
                    </xsl:for-each>
                </InvoiceLines>
            </Invoice> 
        </xsl:for-each>
    </Invoices>
</xsl:template>

</xsl:stylesheet>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!