Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
524 views
in Technique[技术] by (71.8m points)

xslt 1.0 - Multiple groupings of XML nodes

I'm trying to group the input below by the destination and assortment values using muenchian-grouping which is new for me so I'm not sure how to do it properly. The input files will be much larger than this so performance is important.

<?xml version="1.0"?>
<ns0:Data xmlns:ns0="http://BizTalk_Projects.input">
    <transports>
        <destination>destination 1</destination>
        <assortment>Volvo_GA961</assortment>
        <quantity>10</quantity>
    </transports>
    <transports>
        <destination>destination 1</destination>
        <assortment>Volvo_GA961</assortment>
        <quantity>15</quantity>
    </transports>
    <transports>
        <destination>destination 1</destination>
        <assortment>Volvo_GA969</assortment>
        <quantity>15</quantity>
    </transports>   
    <transports>
        <destination>destination 1</destination>
        <assortment>Volvo_GA972</assortment>
        <quantity>5</quantity>
    </transports>   
    <transports>
        <destination>destination 1</destination>
        <assortment>Volvo_SA980</assortment>
        <quantity>20</quantity>
    </transports>   
    <transports>
        <destination>destination 2</destination>
        <assortment>Volvo_GA960</assortment>
        <quantity>10</quantity>
    </transports>
    <transports>
        <destination>destination 1</destination>
        <assortment>Nissan_GA963</assortment>
        <quantity>5</quantity>
    </transports>   
    <transports>
        <destination>destination 1</destination>
        <assortment>Nissan_GA963</assortment>
        <quantity>5</quantity>
    </transports>
</ns0:Data>

Expected output:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Destinations xmlns:ns0="http://BizTalk_Projects.output">
    <Destination>
        <name>destination 1</name>
        <assortment>
            <name>Volvo_GA</name>
            <row>
                <type>sumPerAssortment</type>
                <id>961</id>
                <totalQuantity>25</totalQuantity>
                <region>1</region>
            </row>
            <row>
                <type>sumPerAssortment</type>
                <id>969</id>
                <totalQuantity>15</totalQuantity>
                <region>1</region>
            </row>          
            <row>
                <type>sumPerAssortment</type>
                <id>972</id>
                <totalQuantity>5</totalQuantity>
                <region>2</region>
            </row>      
            <row>
                <type>sumPerRegion</type>
                <id />
                <totalQuantity>40</totalQuantity>
                <region>1</region>
            </row>          
            <row>
                <type>sumPerRegion</type>
                <id />
                <totalQuantity>5</totalQuantity>
                <region>2</region>
            </row>
            <row>
                <type>totalSum</type>
                <id />
                <totalQuantity>45</totalQuantity>
                <region />
            </row>          
        </assortment>
        <assortment>
            <name>Volvo_SA</name>
            <row>
                <type>sumPerAssortment</type>
                <id>980</id>
                <totalQuantity>20</totalQuantity>
                <region>3</region>
            </row>  
            <row>
                <type>sumPerRegion</type>
                <id />
                <totalQuantity>20</totalQuantity>
                <region>3</region>
            </row>  
            <row>
                <type>totalSum</type>
                <id />
                <totalQuantity>20</totalQuantity>
                <region />
            </row>                  
        </assortment>       
        <assortment>
            <name>Nissan_GA</name>
            <row>
                <type>sumPerAssortment</type>
                <id>963</id>
                <totalQuantity>10</totalQuantity>
                <region>1</region>
            </row>  
            <row>
                <type>sumPerRegion</type>
                <id />
                <totalQuantity>10</totalQuantity>
                <region>1</region>
            </row>  
            <row>
                <type>totalSum</type>
                <id />
                <totalQuantity>10</totalQuantity>
                <region />
            </row>          
        </assortment>
    </Destination>
    <Destination>
        <name>destination 2</name>
        <assortment>
            <name>Volvo_GA</name>
            <row>
                <type>sumPerAssortment</type>
                <id>960</id>
                <totalQuantity>10</totalQuantity>
                <region>1</region>
            </row>
            <row>
                <type>sumPerRegion</type>
                <id />
                <totalQuantity>10</totalQuantity>
                <region>1</region>
            </row>          
            <row>
                <type>totalSum</type>
                <id />
                <totalQuantity>10</totalQuantity>
                <region />
            </row>                  
        </assortment>       
    </Destination>  
</ns0:Destinations>

Note:

assortment number starting with 96 = region 1

assortment number starting with 97 = region 2

assortment number starting with 98 = region 3

Start of my XSLT:

<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var"
                exclude-result-prefixes="msxsl var s0"
                version="1.0"
                xmlns:s0="http://BizTalk_Projects.input"
                xmlns:ns0="http://BizTalk_Projects.output">
  <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
  <xsl:key name="destinationKey" match="transports" use="destination"/>
  <xsl:template match="/">
    <xsl:apply-templates select="/s0:Data" />
  </xsl:template>

  <xsl:template match="/s0:Data">
    <ns0:Destinations>
      <xsl:for-each select="transports[count(. | key('destinationKey',destination)[1]) = 1]">
        <Destination>
          <name>
            <xsl:value-of select="destination/text()" />
          </name>
          <xsl:for-each select="key('destinationKey',destination)">
            <assortment>
              <name>
                <xsl:value-of select="substring(assortment/text(),1,string-length(assortment)-3)" />
              </name>
            </assortment>
          </xsl:for-each>
        </Destination>
      </xsl:for-each>
    </ns0:Destinations>
  </xsl:template>
</xsl:stylesheet>

With this code, I'm getting this output (duplicate rows, but correct assortments for each destination);

<ns0:Destinations xmlns:ns0="http://BizTalk_Projects.output">
    <Destination>
        <name>destination 1</name>
        <assortment>
            <name>Volvo_GA</name>
        </assortment>
        <assortment>
            <name>Volvo_GA</name>
        </assortment>
        <assortment>
            <name>Volvo_GA</name>
        </assortment>
        <assortment>
            <name>Volvo_GA</name>
        </assortment>
        <assortment>
            <name>Volvo_SA</name>
        </assortment>
        <assortment>
            <name>Nissan_GA</name>
        </assortment>
        <assortment>
            <name>Nissan_GA</name>
        </assortment>
    </Destination>
    <Destination>
        <name>destination 2</name>
        <assortment>
            <name>Volvo_GA</name>
        </assortment>
    </Destination>
</ns0:Destinations>

Any suggestions on how I can solve this? Help is very appreciated!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's difficult to see how exactly the output relates to the input. Try this as your starting point:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="transports-by-destination" match="transports" use="destination" />
<xsl:key name="transports-by-assortment" match="transports" use="concat(destination, '|', assortment)" />

<xsl:template match="/*">
    <xsl:copy>
        <!-- for each unique destination -->
        <xsl:for-each select="transports[count(. | key('transports-by-destination', destination)[1]) = 1]">
            <Destination>
                <name>
                    <xsl:value-of select="destination"/>
                </name>
                <xsl:variable name="group" select="key('transports-by-destination', destination)" />
                <!-- for each unique assortment in this destination -->
                <xsl:for-each select="$group[count(. | key('transports-by-assortment', concat(destination, '|', assortment))[1]) = 1]">
                    <assortment>
                        <name>
                            <xsl:value-of select="assortment"/>
                        </name>
                        <!-- process this subgroup -->
                        <xsl:for-each select="key('transports-by-assortment', concat(destination, '|', assortment))" >
                            <row>
                                <!-- not sure what goes in here -->
                                <totalQuantity>
                                    <xsl:value-of select="quantity"/>
                                </totalQuantity>
                            </row>
                        </xsl:for-each>
                    </assortment>
                </xsl:for-each>
            </Destination>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...