xsl-list
[Top] [All Lists]

Re: [xsl] XML: From flat to hierarchical with grouping

2017-03-29 08:32:24
You can adapt the code at

http://stackoverflow.com/questions/42932880/

which gives a general approach to converting a flat sequence with level numbers 
into a nested hierarchy.

This approach handles an arbitrary number of levels; if you only have a maximum 
of three then you could possibly simplify it a little.

Michael Kay
Saxonica


On 29 Mar 2017, at 03:12, nick public nickpubl(_at_)gmail(_dot_)com 
<xsl-list-service(_at_)lists(_dot_)mulberrytech(_dot_)com> wrote:

I need to manipolate this XML:

<root>
 <row>
   <rec1>
     <fld1-1/>
   </rec1>
   <rec2>
     <fld2-1/>
   </rec2>
   <rec3>
     <fld3-1/>
   </rec3>
   <rec3>
     <fld3-2/>
   </rec3>
   <rec2>
     <fld2-2/>
   </rec2>
   <rec3>
     <fld3-3/>
   </rec3>
   <rec3>
     <fld3-4/>
   </rec3>
 </row>
 <row>
   <rec1>
     <fld1-2/>
   </rec1>
   <rec2>
     <fld2-3/>
   </rec2>
   <rec3>
     <fld3-5/>
   </rec3>
   <rec3>
     <fld3-6/>
   </rec3>
   <rec2>
     <fld2-4/>
   </rec2>
   <rec3>
     <fld3-7/>
   </rec3>
   <rec3>
     <fld3-8/>
   </rec3>
 </row>
</root>

to convert it in this other hierarchical structure
<root_new>
  <row>
     <rec1>
        <fld1-1/>
        <rec2>
           <fld2-1/>
           <rec3>
              <fld3-1/>
           </rec3>
           <rec3>
              <fld3-2/>
           </rec3>
        </rec2>
        <rec2>
           <fld2-2/>
           <rec3>
              <fld3-3/>
           </rec3>
           <rec3>
              <fld3-4/>
           </rec3>
        </rec2>
     </rec1>
  </row>
  <row>
     <rec1>
        <fld1-2/>
        <rec2>
           <fld2-3/>
           <rec3>
              <fld3-5/>
           </rec3>
           <rec3>
              <fld3-6/>
           </rec3>
        </rec2>
        <rec2>
           <fld2-4/>
           <rec3>
              <fld3-7/>
           </rec3>
           <rec3>
              <fld3-8/>
           </rec3>
        </rec2>
     </rec1>
  </row>
</root_new>

To better explain, for each <row> element I have to include in <rec1>,
just 1 per <row>, all <rec2> in same <row> and in each <rec2> all
following <rec3> until next <rec2> in same <row>.

row-rec1-rec2-rec3-rec3-rec2-rec3

have to e transformed in
row
 rec1
    rec2
       rec3
       rec3
    rec2
       rec3

<rec1>, <rec2> and <rec3> have own fields <fld*>.

With following script

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
   xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
exclude-result-prefixes="msxsl"

 <xsl:output method="xml" indent="yes"/>
 <xsl:key name="k2" match="rec2"
use="generate-id(preceding-sibling::rec1[1])" />
 <xsl:key name="k3" match="rec3"
use="generate-id(preceding-sibling::rec2[1])" />

 <xsl:template match="/">
   <root_new>
     <xsl:apply-templates select="//root/row" />
   </root_new>
 </xsl:template>

 <xsl:template match="//row">
   <xsl:copy>
     <xsl:apply-templates select="rec1" />
   </xsl:copy>
 </xsl:template>

 <xsl:template match="rec1">
   <xsl:copy>
     <xsl:copy-of select="./*"/>
     <xsl:copy-of select="key('k2', generate-id())"/>
     <xsl:apply-templates select="rec2" />
   </xsl:copy>
 </xsl:template>

 <xsl:template match="rec2">
   <xsl:copy>
     <xsl:copy-of select="./*"/>
     <xsl:copy-of select="key('k3', generate-id())"/>
   </xsl:copy>
 </xsl:template>

</xsl:stylesheet>

I can obtain this partial result

<?xml version="1.0" encoding="utf-8"?>
<root_new>
 <row>
   <rec1>
     <fld1-1 />
     <rec2>
       <fld2-1 />
     </rec2>
     <rec2>
       <fld2-2 />
     </rec2>
   </rec1>
 </row>
 <row>
   <rec1>
     <fld1-2 />
     <rec2>
       <fld2-3 />
     </rec2>
     <rec2>
       <fld2-4 />
     </rec2>
   </rec1>
 </row>
</root_new>

but I'm not able to include the <rec3> elements under the <rec2> that
precede them.

Could you help me please?

Ciao from Italy
Nicola





--------------------------------------------------------

Do you need to index your XML? Try the OpenSource XMLSmartHelper Framework

--~----------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
EasyUnsubscribe: http://lists.mulberrytech.com/unsub/xsl-list/1167547
or by email: xsl-list-unsub(_at_)lists(_dot_)mulberrytech(_dot_)com
--~--

<Prev in Thread] Current Thread [Next in Thread>