Pavel Košek
Pavel Košek

Reputation: 3

XSLT transform flat tree structure to list

I have an xml file that describes the tree structure of the eshop, and I only need to get a list of all the child groups. I don't know how many parent/child levels is in structure. The input xml looks like this: '''

 <items>
  <item>
   <id>1</id>
   <parent_id>0</parent_id>
   <name>Cars</name>
  </item>
  <item>
   <id>2</id>
   <parent_id>0</parent_id>
   <name>Tools</name>
  </item>

  <item>
   <id>1001</id>
   <parent_id>1</parent_id>
   <name>Ford</name>
  </item>
  <item>
   <id>1002</id>
   <parent_id>1</parent_id>
   <name>Toyota</name>
  </item>
  <item>
   <id>5</id>
   <parent_id>2</parent_id>
   <name>Axe</name>
  </item>
  <item>
   <id>1150</id>
   <parent_id>1001</parent_id>
   <name>Ka</name>
  </item>
  <item>
   <id>1151</id>
   <parent_id>1001</parent_id>
   <name>Raptor</name>
  </item>
</export>

'''

The output should look like a simple list of all child groups, the structure doesn't matter much, sorting is also not important. '''

<groups>
<root>
<ID>1</ID>
<Child_ID>1001</Child_ID>
<Child_ID>1002</Child_ID>
<Child_ID>1150</Child_ID>
<Child_ID>1151</Child_ID>
</root>
<root>
<ID>2</ID>
<Child_ID>5</Child_ID>
</root>
</groups>

'''

Can you advise me on what functions or procedures to transform?

Upvotes: 0

Views: 103

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116982

Here's one way you could look at it:

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:key name="child" match="item" use="parent_id"/>

<xsl:template match="items">
    <groups>
        <xsl:for-each select="item[parent_id=0]">
            <group>
                <ID>
                    <xsl:value-of select="id" />
                </ID>
                <xsl:apply-templates select="key('child', id)"/>
            </group>
        </xsl:for-each>
    </groups>
</xsl:template>

<xsl:template match="item">
    <Child_ID>
        <xsl:value-of select="id" />
    </Child_ID>
    <xsl:apply-templates select="key('child', id)"/>
</xsl:template>

</xsl:stylesheet>

With a well-formed (!) input such as:

XML

<items>
    <item>
        <id>1</id>
        <parent_id>0</parent_id>
        <name>Cars</name>
    </item>
    <item>
        <id>2</id>
        <parent_id>0</parent_id>
        <name>Tools</name>
    </item>
    <item>
        <id>1001</id>
        <parent_id>1</parent_id>
        <name>Ford</name>
    </item>
    <item>
        <id>1002</id>
        <parent_id>1</parent_id>
        <name>Toyota</name>
    </item>
    <item>
        <id>5</id>
        <parent_id>2</parent_id>
        <name>Axe</name>
    </item>
    <item>
        <id>1150</id>
        <parent_id>1001</parent_id>
        <name>Ka</name>
    </item>
    <item>
        <id>1151</id>
        <parent_id>1001</parent_id>
        <name>Raptor</name>
    </item>
</items>

this will produce:

Result

<?xml version="1.0" encoding="UTF-8"?>
<groups>
  <group>
    <ID>1</ID>
    <Child_ID>1001</Child_ID>
    <Child_ID>1150</Child_ID>
    <Child_ID>1151</Child_ID>
    <Child_ID>1002</Child_ID>
  </group>
  <group>
    <ID>2</ID>
    <Child_ID>5</Child_ID>
  </group>
</groups>

Upvotes: 1

Related Questions