Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Dot separate attribute values to nested XML elements

Given a source XML instance as follows:

source.xml

<?xml version="1.0" encoding="UTF-8"?>
<data>
  <elements>
    <element path="a." name="Aname"/>
    <element path="a.b." parent="a." name="Bname"/>
    <element path="a.c." parent="a." name="Cname"/>
    <element path="a.c.d." parent="a.c." name="Dname"/>
    <element path="a.c.d.e." parent="a.c.d." name="Ename"/>
    <element path="a.f." parent="a." name="Fname"/>
    <element path="a.f.g." parent="a.f." name="Gname"/>
    <element path="a.f.g.h." parent="a.f.g." name="Hname"/>
    <element path="a.f.g.h.i." parent="a.f.g.h." name="Iname"/>
    <element path="a.f.g.h.i.j." parent="a.f.g.h.i." name="Jname"/>
    <element path="a.f.g.k." parent="a.f.g." name="Kname"/>
    <element path="a.f.g.l." parent="a.f.g." name="Lname"/>
    <element path="a.f.m." parent="a.f." name="Mname"/>
  </elements>
</data>

How can the following resultant XML be achieved via an XSLT transformation:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

result.xml

<?xml version="1.0" encoding="UTF-8"?>
<map>
  <node TEXT="Aname">
    <node TEXT="Bname"/>
    <node TEXT="Cname">
      <node TEXT="Dname">
        <node TEXT="Ename"/>
      </node>
    </node>
    <node TEXT="Fname">
      <node TEXT="Gname">
        <node TEXT="Hname">
          <node TEXT="Iname">
            <node TEXT="Jname"/>
          </node>
        </node>
        <node TEXT="Kname"/>
        <node TEXT="Lname"/>
      </node>
      <node TEXT="Mname"/>
    </node>
  </node>
</map>

As you can see in the source XML every element XML element has an associated path attribute with a dot separated string value.
Every element in the source XML also has a parent attribute with a dot separated string value.

Can the values of both these attributes (path and parent) somehow be utilized to achieve the desired nesting of node elements as shown in the resultant XML ?

Below is just one example of my many failed XSLT attempts.
All attempts I’ve tried fail to achieve the desired nesting of node elements – the resultant XML always remains flat.

XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

  <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="data">
    <map>
      <xsl:apply-templates select="@*|node()"/>
    </map>
  </xsl:template>

  <xsl:template match="element">
    <xsl:for-each select=".">
      <node>
        <xsl:attribute name="TEXT" select="@name"/>
      </node>
    </xsl:for-each>
  </xsl:template>

</xsl:stylesheet>

>Solution :

This can be very easy it you use the correct tool for resolving cross-references:

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="element" use="@parent" />

<xsl:template match="/data">
    <map>
        <xsl:apply-templates select="elements/element[not(@parent)]"/>
    </map>
</xsl:template>

<xsl:template match="element">
    <node TEXT="{@name}">
        <xsl:apply-templates select="key('child', @path)"/>
    </node>
</xsl:template>

</xsl:stylesheet>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading