1

Hello I have a requirement where I have an xml file (generic the element names and nodes may change). The intention is to produce a properties file out of it where on left side will be the absolute path of the element name and right side is the value for that element. for instance :-

If I have below xml :-

<?xml version="1.0" encoding="UTF-8"?>
<group>
<root>
  <child>
    <subchild>xyz</subchild>
  </child>
</root>
<root1>
  <child>
    <subchild>abc</subchild>
  </child>
</root1>
<root2>
  <child>
    <subchild>pqr</subchild>
  </child>
</root2>
<root3>
  <child>
    <subchild>lmn</subchild>
  </child>
</root3>
</group>

then the output should be :-

/group/root/child/subchild=xyz
/group/root1/child/subchild=abc
/group/root2/child/subchild=pqr
/group/root3/child/subchild=lmn

So far I have written below xslt but it does not work correctly:-

<?xml version="1.0"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="text" />

    <xsl:template match="node()">
        <xsl:for-each select="ancestor-or-self::*">
            <xsl:value-of select="concat('/',name(.))"/>
        </xsl:for-each>
<xsl:value-of select="concat('=',.)"/>
        <xsl:text>&#xA;</xsl:text>

        <xsl:apply-templates select="*"/>
    </xsl:template>
</xsl:transform>

any help would be much appreciated.

thansk.

  • 1
    Please note that I am looking in to a generic solution since the structure of xml may differ but the xml does not contain any attributes or repeated complex elements at the same heriarchy. – Indrajeet Kumar May 11 '18 at 04:46
  • I have just answered your question, let me know if it works fine for you Thanks – Allan May 11 '18 at 05:34

1 Answers1

1

You can use the following stylesheet for your specific case:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="*">
      <xsl:if test="not(*)">
         <xsl:apply-templates select="ancestor-or-self::*" mode="path"/>
         <xsl:value-of select="concat('=',.)"/>
         <xsl:text>&#xA;</xsl:text>
        </xsl:if>
        <xsl:apply-templates select="*"/>
    </xsl:template>

    <xsl:template match="*" mode="path">
        <xsl:value-of select="concat('/',name())"/>
    </xsl:template>

</xsl:stylesheet>

INPUT:

more group.xml 
<?xml version="1.0" encoding="UTF-8"?>
<group>
<root>
  <child>
    <subchild>xyz</subchild>
  </child>
</root>
<root1>
  <child>
    <subchild>abc</subchild>
  </child>
</root1>
<root2>
  <child>
    <subchild>pqr</subchild>
  </child>
</root2>
<root3>
  <child>
    <subchild>lmn</subchild>
  </child>
</root3>
</group>

OUTPUT:

xsltproc pathGen.xsl group.xml
/group/root/child/subchild=xyz
/group/root1/child/subchild=abc
/group/root2/child/subchild=pqr
/group/root3/child/subchild=lmn

If you have a more complex structure with attributes and several siblings I would recommend you to adapt the solution of dimitre-novatchev -> General Solution

Allan
  • 12,117
  • 3
  • 27
  • 51