简体   繁体   中英

XSLT- Create a tree from XML

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.

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