XML - combine tags to children with XSLT

2019-09-03 10:45发布

I have an XML which looks like this:

<?xml version="1.0"?>                                                                                                                                 
<ROWSET>                                                                                                                                              
 <ROW>                                                                                                                                                
  <KUNDENNR>63564</KUNDENNR>                                                                                                                          
  <JAHR>2012</JAHR>                                                                                                                                   
  <MONAT>2</MONAT>                                                                                                                                    
  <NAME>John Doe</NAME>                                                                                                                       
  <NETTO>504,66</NETTO>                                                                                                                               
  <DB_BASIS>21,56</DB_BASIS>                                                                                                                          
  <EKECHT>482,56</EKECHT>                                                                                                                             
  <NAME1>Some Name</NAME1>                                                                                                                       
  <NAME2>BA 31 (BÜRO GGR 1)</NAME2>                                                                                                                   
  <LAND>AT</LAND>                                                                                                                                     
  <PLZ>1082</PLZ>                                                                                                                                     
  <ORT>Wien</ORT>                                                                                                                                     
  <ADM>Henry Ford</ADM>                                                                                                                          
  <KUNDENKLASSE>A</KUNDENKLASSE>                                                                                                                      
  <UEBERKUNDE>Some Value</UEBERKUNDE>                                                                                                             
  <HANDLING>22,577179011</HANDLING>                                                                                                                   
  <SOLLFRACHT>22,68</SOLLFRACHT>              
  <DG_BASIS_P>-10,763888888888888888888888888888888889</DG_BASIS_P>                                                                                   
 </ROW> 
 <ROW>                                                                                                                                                
  <KUNDENNR>63564</KUNDENNR>                                                                                                                          
  <JAHR>2011</JAHR>                                                                                                                                   
  <MONAT>1</MONAT>                                                                                                                                    
  <NAME>John Doe</NAME>                                                                                                                       
  <NETTO>502,66</NETTO>                                                                                                                               
  <DB_BASIS>21,56</DB_BASIS>                                                                                                                          
  <EKECHT>482,56</EKECHT>                                                                                                                             
  <NAME1>Some Name</NAME1>                                                                                                                       
  <NAME2>BA 31 (BÜRO GGR 1)</NAME2>                                                                                                                   
  <LAND>AT</LAND>                                                                                                                                     
  <PLZ>1082</PLZ>                                                                                                                                     
  <ORT>Wien</ORT>                                                                                                                                     
  <ADM>Henry Ford</ADM>                                                                                                                          
  <KUNDENKLASSE>A</KUNDENKLASSE>                                                                                                                      
  <UEBERKUNDE>Some value</UEBERKUNDE>                                                                                                             
  <HANDLING>22,577179011</HANDLING>                                                                                                                   
  <SOLLFRACHT>22,68</SOLLFRACHT>              
  <DG_BASIS_P>-10,538888888888888888889</DG_BASIS_P>                                                                                   
 </ROW> 
</ROWSET>

note that the first and last -elements have the same value within . Now I would like to transform that XML into the following structure with XSLT:

<?xml version="1.0"?>                                                                                                                                 
<ROWSET>                                                                                                                                              
 <KUNDE>
  <KUNDENNR>63564</KUNDENNR>                                                                                                                          
  <NAME>John Doe</NAME>      
  <NAME1>Some Name</NAME1>                                                                                                                       
  <NAME2>BA 31 (B RO GGR 1)</NAME2>                                                                                                                   
  <LAND>AT</LAND>                                                                                                                                     
  <PLZ>1082</PLZ>                                                                                                                                     
  <ORT>Wien</ORT>                                                                                                                                     
  <ADM>Henry Ford</ADM>                                                                                                                          
  <KUNDENKLASSE>A</KUNDENKLASSE>    
  <UEBERKUNDE>Some Value</UEBERKUNDE>                                                                                                              
    <ROW>                                                                                                                                                
        <JAHR>2012</JAHR>                                                                                                                                   
        <MONAT>2</MONAT>                                                                                                                                    
        <NETTO>504,66</NETTO>                                                                                                                               
        <DB_BASIS>21,56</DB_BASIS>                                                                                                                          
        <EKECHT>482,56</EKECHT>                                                                                                                             
        <HANDLING>22,577179011</HANDLING>                                                                                                                   
        <SOLLFRACHT>22,68</SOLLFRACHT>                                                                                                                      
        <DG_BASIS_P>4,27218325209051638727063765703642056038</DG_BASIS_P>                                                                                   
    </ROW>
    <ROW>
        <JAHR>2012</JAHR>                                                                                                                                   
        <MONAT>1</MONAT>                                                                                                                                    
        <NETTO>502,66</NETTO>                                                                                                                              
        <DB_BASIS>21,56</DB_BASIS>                                                                                                                        
        <EKECHT>482,56</EKECHT>                                                                                                                           
        <HANDLING>22,577179011</HANDLING>                                                                                                                    
        <SOLLFRACHT>22,68</SOLLFRACHT>                                                                                                                      
        <DG_BASIS_P>-10,538888888888888888889</DG_BASIS_P>                                                                                   
    </ROW>  
 </KUNDE> 
 </ROWSET>

The XML is exported from a DB and it's necessary for me to get it into a better structure. I have tried several different things with XSLT but I'm new to XSLT and would like to kindly ask for help.

Thank you in advance.

标签: xml xslt
1条回答
Fickle 薄情
2楼-- · 2019-09-03 11:13

You can use XSLT grouping, which is a XSLT 2.0 feature.

The trick is to use <xsl:for-each-group> element.

Please note that the following code is not complete - you need to <copy-of ...> all the nodes you need.

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

  <xsl:template match="ROWSET">
    <ROWSET>
      <xsl:for-each-group select="ROW" group-by="KUNDENNR">
        <KUNDE>
          <!-- this is the common part -->
          <xsl:copy-of select="NAME1" />
          <xsl:copy-of select="UEBERKUNDE" />

          <!-- iterate over every ROW in the group -->
          <xsl:for-each select="current-group()">
            <ROW>
              <xsl:copy-of select="JAHR" />
              <xsl:copy-of select="MONAT" />
            </ROW>
          </xsl:for-each>

        </KUNDE>
      </xsl:for-each-group>
    </ROWSET>
  </xsl:template>
</xsl:stylesheet>

Given your XML document and the XSLT above, the output would be:

<?xml version="1.0" encoding="UTF-8"?>
<ROWSET>
   <KUNDE>
      <NAME1>Some Name</NAME1>
      <UEBERKUNDE>Some Value</UEBERKUNDE>
      <ROW>
         <JAHR>2012</JAHR>
         <MONAT>2</MONAT>
      </ROW>
      <ROW>
         <JAHR>2011</JAHR>
         <MONAT>1</MONAT>
      </ROW>
   </KUNDE>
</ROWSET>

You can also read this article which has some nice examples of using for-each-group.

查看更多
登录 后发表回答