I want to create an XML with a hierarchic structure from a flat XML file. The XML file contains the parent-child relations and if a node is a leaf or not.
There is no explicit information about the level of nesting or the root nodes in the structure. The XML-file can contain more than one root element and it is not ordered.
<list>
<stru><parent>A01</parent><child>P04</child></stru>
<stru><parent>B11</parent><child>P01</child></stru>
<stru><parent>B12</parent><child>P01</child></stru>
<stru><parent>B12</parent><child>P03</child></stru>
<stru><parent>B21</parent><child>P02</child></stru>
<stru><parent>B21</parent><child>P03</child></stru>
<item><cod>B01</cod><isparent>Y</isparent></item>
<item><cod>B11</cod><isparent>Y</isparent></item>
<item><cod>B12</cod><isparent>Y</isparent></item>
<item><cod>B21</cod><isparent>Y</isparent></item>
<item><cod>P01</cod><isparent>N</isparent></item>
<item><cod>P02</cod><isparent>N</isparent></item>
<item><cod>P03</cod><isparent>N</isparent></item>
<item><cod>A01</cod><isparent>Y</isparent></item>
<item><cod>P04</cod><isparent>N</isparent></item>
<stru><parent>B01</parent><child>B11</child></stru>
<stru><parent>B01</parent><child>B12</child></stru>
<stru><parent>B11</parent><child>B21</child></stru>
</list>
The needed result is shown below. I don't know how to do this.
I found a transformation that creates that structure if the root node is known.
<list>
<itemlist>
<item>
<cod>A01</cod>
<itemlist>
<item>
<cod>P04</cod>
</item>
</itemlist>
</item>
<item>
<cod>B01</cod>
<itemlist>
<item>
<cod>B11</cod>
<itemlist>
<item>
<cod>B21</cod>
<itemlist>
<item>
<cod>P02</cod>
</item>
<item>
<cod>P03</cod>
</item>
</itemlist>
</item>
<item>
<cod>P01</cod>
</item>
</itemlist>
</item>
<item>
<cod>B12</cod>
<itemlist>
<item>
<cod>P01</cod>
</item>
<item>
<cod>P02</cod>
</item>
</itemlist>
</item>
</itemlist>
</item>
</itemlist>
</list>
The following stylesheet:
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="link-by-child" match="stru" use="child" />
<xsl:key name="link-by-parent" match="stru" use="parent" />
<xsl:key name="item-by-code" match="item" use="cod" />
<xsl:template match="/">
<list>
<itemlist>
<!-- select progenitors (items that are not children of any other item) -->
<xsl:apply-templates select="list/item[not(key('link-by-child', cod))]"/>
</itemlist>
</list>
</xsl:template>
<xsl:template match="item[isparent='Y']">
<xsl:copy>
<xsl:copy-of select="cod"/>
<itemlist>
<!-- select item's children -->
<xsl:apply-templates select="key('item-by-code', key('link-by-parent', cod)/child)"/>
</itemlist></xsl:copy>
</xsl:template>
<xsl:template match="item[isparent='N']">
<xsl:copy>
<xsl:copy-of select="cod"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
when applied to your example input, will return:
<?xml version="1.0" encoding="UTF-8"?>
<list>
<itemlist>
<item>
<cod>B01</cod>
<itemlist>
<item>
<cod>B11</cod>
<itemlist>
<item>
<cod>B21</cod>
<itemlist>
<item>
<cod>P02</cod>
</item>
<item>
<cod>P03</cod>
</item>
</itemlist>
</item>
<item>
<cod>P01</cod>
</item>
</itemlist>
</item>
<item>
<cod>B12</cod>
<itemlist>
<item>
<cod>P01</cod>
</item>
<item>
<cod>P03</cod>
</item>
</itemlist>
</item>
</itemlist>
</item>
<item>
<cod>A01</cod>
<itemlist>
<item>
<cod>P04</cod>
</item>
</itemlist>
</item>
</itemlist>
</list>
which I believe is identical to your expected output, except for the ordering of the branches.
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.