简体   繁体   中英

XML transformation using XSLT by grouping the tags based on some value

I am trying to transform one XML by creating a new tag by grouping the tags. like group the items which are having same parent value.

 <root>
   <item id="100">
      <properties>
         <property attribute-id="parent">10</property>
      </properties>
      <properties>
         <property attribute-id="amount">1.1</property>
      </properties>
   </item>
   <item id="101">
      <properties>
         <property attribute-id="parent">10</property>
      </properties>
      <properties>
         <property attribute-id="amount">1.1</property>
      </properties>
   </item>
   <item id="102">
      <properties>
         <property attribute-id="parent">11</property>
      </properties>
      <properties>
         <property attribute-id="amount">1.1</property>
      </properties>
   </item>
   <item id="103">
      <properties>
         <property attribute-id="parent">10</property>
      </properties>
      <properties>
         <property attribute-id="amount">1.1</property>
      </properties>
   </item>
   <item id="104">
      <properties>
         <property attribute-id="parent">11</property>
      </properties>
      <properties>
         <property attribute-id="amount">1.1</property>
      </properties>
   </item>
</root>

New tag should be:

<item id = "10">  
       <childs>
         <child id="100" />
         <child id="101" />
         <child id="102" />
       </childs>
    </item>       
    <item id = "11">
       <childs>
         <child id="104" />
         <child id="105" />
       </childs>
    </item> 

Is this possible with XSLT?
How can this be done in XSLT?

Editing the initial post i have faced some issues when the tag was in attribute format. Tried updating the first solution but the attribute form is causing many problems.

You can achieve with this the XSLT-1.0 method Muenchian Grouping . If you search on SO, you'll find a lot of examples. Applying this method, your stylesheet could look like this (I added a hypothetical <root> element around your source XML to make it well-formed ):

The xsl:key and the select expression of the outer xsl:for-each do implement the Muenchian Grouping . The inside of the loop should be kind of self-explaining.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="id" match="item" use="properties/property[@attribute-id='parent']" />   

<xsl:template match="/root">
    <xsl:copy>
        <xsl:for-each select="item[generate-id() = generate-id(key('id',properties/property[@attribute-id='parent'])[1])]">
            <item id="{parent}">
                <childs>
                    <xsl:for-each select="key('id',properties/property[@attribute-id='parent'])">
                        <child id="{@id}" />
                    </xsl:for-each>
                </childs>
            </item>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

If you can use XSLT-2.0 or above, you can make use of xsl:for-each-group like this:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>

<xsl:template match="/root">
    <xsl:copy>
        <xsl:for-each-group select="item" group-by="properties/property[@attribute-id='parent']">
            <item id="{parent}">
                <childs>
                    <xsl:for-each select="current-group()">
                        <child id="{@id}" />
                    </xsl:for-each>
                </childs>
            </item>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

It is slightly more simple, but does the same.


Its output, in both cases, is:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <item id="">
      <childs>
         <child id="100"/>
         <child id="101"/>
         <child id="103"/>
      </childs>
   </item>
   <item id="">
      <childs>
         <child id="102"/>
         <child id="104"/>
      </childs>
   </item>
</root>

It's not exactly what you want, but I guess that the last child id's of your example are wrong.

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