简体   繁体   中英

XSLT: Merge two nodes

I would like to convert below XML through XSLT by groping based on Email tag and merge two nodes into one and get all the elements in one node. Please advise

Input XML:

<?xml version="1.0" encoding="UTF-8"?>
<Details>  
    <Worker>
        <Name>AAA</Name>
        <Email>AAA@test.com</Email>
        <Item>BBB</Item>
        <Avg_Amount>425.20</Avg_Amount>
    </Worker>
    <Worker>
        <Manager>AAA</Manager>
        <Email>AAA@test.com</Email>
        <Item>BBB</Item>
        <Draft_Amount>1826.64</Draft_Amount>
    </Worker>   
</Details>

XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wd="urn:com.test/bsvc" exclude-result-prefixes="wd">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    
    <xsl:template match="/">
        
        <Transactions>
            
            <xsl:for-each-group select="Details/Worker" group-by='Email'>
                
                <Manager>             
                    <Name>
                        <xsl:value-of select="Name"/>
                    </Name>
                    <Email>
                        <xsl:value-of select="Email"/>
                    </Email>
                    
                    
                    <xsl:for-each-group select="current-group()" group-by="Item">
                        
                        <Worker>
                            <Name>
                                <xsl:value-of select="Name"/>
                            </Name>
                            <Email>
                                <xsl:value-of select="Email"/>
                            </Email>
                            <Item>
                                <xsl:value-of select="Item"/>
                            </Item>
                            
                            <Avg_Amount>
                                <xsl:value-of select="Avg_Amount"/>
                            </Avg_Amount>
                            <Draft_Amount>
                                <xsl:value-of select="Charges_Draft"/>
                            </Draft_Amount>
                            
                            
                        </Worker>
                        
                        
                        
                    </xsl:for-each-group>
                    
                </Manager>
                
            </xsl:for-each-group>
            
        </Transactions>
    </xsl:template>
</xsl:stylesheet>

Output generated:

<Transactions>
   <Manager>
      <Name>AAA</Name>
      <Email>AAA@test.com</Email>
      <Worker>
         <Name>AAA</Name>
         <Email>AAA@test.com</Email>
         <Item>BBB</Item>
         <Avg_Amount>425.20</Avg_Amount>
         <Draft_Amount/>
      </Worker>
   </Manager>
</Transactions>

Desired Output:

<Transactions>
   <Manager>
      <Name>AAA</Name>
      <Email>AAA@test.com</Email>
      <Worker>
         <Name>AAA</Name>
         <Email>AAA@test.com</Email>
         <Item>BBB</Item>
         <Avg_Amount>425.20</Avg_Amount>
         <Draft_Amount>1826.64</Draft_Amount>
      </Worker>
   </Manager>
</Transactions>

I would like to convert below XML through XSLT by groping based on Email tag and merge two nodes into one and get all the elements in one node. Please advise

Change the Draft_Amount to select Draft_Amount from the current-group() :

<Draft_Amount>
  <xsl:value-of select="current-group()/Draft_Amount"/>
</Draft_Amount>

But should consider what you would want to do if there are more than one Draft_Amount among multiple Worker . You could average them, select the first, etc.

Also, your example data only has one Avg_Amount element, but you might consider changing Avg_Amount to compute the average of all Avg_Amount .

<Avg_Amount>
  <xsl:value-of select="avg(current-group()/Avg_Amount)"/>
</Avg_Amount>

You could eliminate the extra xsl:for-each , and could simplify the code a bit and just copy some of those elements, instead of recreating the element and selecting the values:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:wd="urn:com.test/bsvc" exclude-result-prefixes="wd">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    
    <xsl:template match="/"> 
        <Transactions>
            <xsl:for-each-group select="Details/Worker" group-by='Email'>     
                <Manager>   
                    <xsl:copy-of select="Name|Email"/>
                    <Worker>
                        <xsl:copy-of select="Name|Email|Item"/>
                        <Avg_Amount>
                            <xsl:value-of select="avg(current-group()/Avg_Amount)"/>
                        </Avg_Amount>
                        <xsl:copy-of select="(current-group()/Draft_Amount)[1]"/>
                    </Worker>
                </Manager>
            </xsl:for-each-group>
        </Transactions>
    </xsl:template>
</xsl:stylesheet>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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