0
votes

I have several files with data and I want to group some nodes and make one file. I have given only 2 sample files but it can be many. The input files are listed in an xml file as includes (list.xml).

Basically, the grouping should be done according to the of each file and each should be listed as node for that particular functional area.

Is this possible to do with XSLT? Maybe with more than one transformation?

File list : list.xml

<?xml version="1.0" encoding="UTF-8"?>
<index xmlns:xi="http://www.w3.org/2001/XInclude">
   <xi:include href="xml/models/1c8dca64-8b40-4e58-8581-5104f5ca3f3e.xml"/>
   <xi:include href="xml/models/7f10e39d-ca8c-4c17-9a0f-2dcbceaaed51.xml"/>
   <xi:include href="xml/models/2d90b9b4-793c-4d8b-9e06-0a93dfa738a2.xml"/>
   <xi:include href="xml/models/4ee7085e-8241-4dae-a095-38ede5fd7fb0.xml"/>
</index>

Input File 01 : 1c8dca64-8b40-4e58-8581-5104f5ca3f3e.xml

<model>
   <contains>
      <vertex>
         <functionalarea>Supply Chain</functionalarea>
         <breakdowns>
            <model>34c1e701-5a70-4493-b877-38624348947c</model>
         </breakdowns>
      </vertex>
      <vertex>
         <functionalarea>Supply Chain</functionalarea>
         <breakdowns>
            <model>25a39e71-aa59-4f63-9c09-8cc4e36bae72</model>
         </breakdowns>
      </vertex>
      <vertex>
         <functionalarea>Planning</functionalarea>
         <breakdowns>
            <model>45c0d6c3-a910-4050-b10e-f17eb7276c44</model>
         </breakdowns>
      </vertex>
   </contains>
</model>

Input File 02 : 7f10e39d-ca8c-4c17-9a0f-2dcbceaaed51.xml

<model>
   <contains>
      <vertex>
         <functionalarea>Supply Chain</functionalarea>
         <breakdowns>
            <model>58a77718-1e95-408b-a6ae-f185348ec310</model>
         </breakdowns>
      </vertex>
      <vertex>
         <functionalarea>Planning</functionalarea>
         <breakdowns>
            <model>87767baa-bab9-46dd-80d8-a0d0c3993429</model>
         </breakdowns>
      </vertex>
      <vertex>
         <functionalarea>Execution</functionalarea>
         <breakdowns>
            <model>f21aef69-9772-49bd-b6c1-4f3e55fc3887</model>
         </breakdowns>
      </vertex>
   </contains>
</model>

Required output

<tree>
    <node>
       <name>Supply Chain</name>
       <children>
          <child>34c1e701-5a70-4493-b877-38624348947c</child>
          <child>25a39e71-aa59-4f63-9c09-8cc4e36bae72</child>
          <child>58a77718-1e95-408b-a6ae-f185348ec310</child>
       </children>
    </node>
    <node>
       <name>Planning</name>
       <children>
          <child>45c0d6c3-a910-4050-b10e-f17eb7276c44</child>
          <child>87767baa-bab9-46dd-80d8-a0d0c3993429</child>
       </children>
    </node>
    <node>
       <name>Execution</name>
       <children>
          <child>f21aef69-9772-49bd-b6c1-4f3e55fc3887</child>
       </children>
    </node>
</tree>
1
You have tagged both [xslt-1.0] and [xslt-2.0]. Which are you actually using?John Bollinger
You have two options, as you use XInclude, you can simply enable XInclude processing in your parser/the parser the XSLT processor uses and then the input processed by XSLT will not contain the xi:include elements but rather the referenced contents and you can simply group it. As an alternative, you can use e.g. document(index/xi:include/@href) to pull in those referenced files and then use grouping. As for grouping, refer to w3.org/TR/xslt20/#grouping-examples.Martin Honnen

1 Answers

1
votes

First bind a variable $models to the set of model elements, which you can do in a number of ways, for example

<xsl:variable name="models" select="//@href/document(.)/*"/>

Then do the grouping:

<xsl:for-each-group select="$models/*/vertex" group-by="functionalarea">
    <node>
       <name><xsl:value-of select="current-grouping-key()"/></name>
       <children>
          <xsl:for-each select="current-group()">
            <child><xsl:value-of select=".//model"/></child>
          </xsl:for-each>
       </children>
    </node>
</xsl:for-each-group>