Hierarchical xml to Flat xml using XSLT

I have an xml that is structured as follows

<root>
  <PNode>
    <node1>
      <node1Child>data</node1Child>
      <node2Child>data</node2Child>
    </node1>
  </PNode>
  <SecondNode>
    <node1>
      <node1Child>
        <child>data</child>
      </node1Child>
    </node1>
  </SecondNode>
</root>

I need output using genric xslt because I have a lot of xml to convert to this format.

<root>
  <Pnode-node1-node1Child>data</Pnode-node1-node1Child>
  <Pnode-node1-node2Child>data</Pnode-node1-node2Child>
  <SecondNode-node1-node1child-child>data</SecondNode-node1-node1child-child>
</root>

It can be deeper or less.
can i do this using XSLT pls give any example or link

I want to do this to create a PDF file from sql 2k8 r2 rdl server. because rdl does not accept nested xml, so you need to smooth it.

+5
source share
4 answers

This style sheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="/*">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*">
        <xsl:param name="pName"/>
        <xsl:apply-templates>
            <xsl:with-param name="pName" select="concat($pName,name(),'-')"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="text()">
        <xsl:param name="pName"/>
        <xsl:element name="{substring($pName,1,string-length($pName)-1)}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Conclusion:

<root>
    <PNode-node1-node1Child>data</PNode-node1-node1Child>
    <PNode-node1-node2Child>data</PNode-node1-node2Child>
    <SecondNode-node1-node1Child-child>data</SecondNode-node1-node1Child-child>
</root>

Update : if there can be empy nodes ...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:strip-space elements="*"/>
    <xsl:template match="/*">
        <xsl:copy>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="*">
        <xsl:param name="pName"/>
        <xsl:apply-templates>
            <xsl:with-param name="pName" select="concat($pName,name(),'-')"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="*[not(*)]">
        <xsl:param name="pName"/>
        <xsl:element name="{$pName}{name()}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

: .

+3

:

<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="/*">
     <root>
      <xsl:apply-templates/>
     </root>
 </xsl:template>

 <xsl:template match="text()">
  <xsl:variable name="vCompName">
   <xsl:for-each select="ancestor::*[not(position() =last())]">
    <xsl:value-of select="translate(name(), ':', '_')"/>
    <xsl:if test="not(position()=last())">-</xsl:if>
   </xsl:for-each>
  </xsl:variable>

  <xsl:element name="{$vCompName}">
   <xsl:value-of select="."/>
  </xsl:element>
 </xsl:template>
</xsl:stylesheet>

XML-:

<root>
    <PNode>
        <node1>
            <node1Child>data</node1Child>
            <node2Child>data</node2Child>
        </node1>
    </PNode>
    <SecondNode>
        <node1>
            <node1Child>
                <child>data</child>
            </node1Child>
        </node1>
    </SecondNode>
</root>

, :

<root>
   <PNode-node1-node1Child>data</PNode-node1-node1Child>
   <PNode-node1-node2Child>data</PNode-node1-node2Child>
   <SecondNode-node1-node1Child-child>data</SecondNode-node1-node1Child-child>
</root>

  • root . , node.

  • , ( ancestor::), '-', string .

  • string-join 2. , ':' . , .

  • , node .

+3

:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <PNode>
        <node1>
            <node1Child>data</node1Child>
            <node2Child>data</node2Child>
        </node1>
    </PNode>
    <SecondNode>
        <node1>
            <node1Child>
                <child>data</child>
            </node1Child>
        </node1>
    </SecondNode>
</root>

:

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

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes" method="xml"/>

    <xsl:template match="root">
        <xsl:copy>
            <xsl:apply-templates select="*" mode="flatten"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[normalize-space(text())]" mode="flatten">
        <xsl:param name="name-prefix" select="''"/>
        <xsl:variable name="name">
            <xsl:call-template name="construct-name">
                <xsl:with-param name="name-prefix" select="$name-prefix"/>
            </xsl:call-template>
        </xsl:variable>

        <xsl:element name="{$name}">
            <xsl:apply-templates select="text()"/>
        </xsl:element>

        <xsl:apply-templates select="node()" mode="flatten">
            <xsl:with-param name="name-prefix" select="$name"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="*[not(normalize-space(text()))]" mode="flatten">
        <xsl:param name="name-prefix" select="''"/>

        <xsl:variable name="prefix">
            <xsl:call-template name="construct-name">
                <xsl:with-param name="name-prefix" select="$name-prefix"/>
            </xsl:call-template>
        </xsl:variable>

        <xsl:apply-templates select="node()" mode="flatten">
            <xsl:with-param name="name-prefix" select="$prefix"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template name="construct-name">
        <xsl:param name="name-prefix"/>
        <xsl:choose>
            <xsl:when test="$name-prefix">
                <xsl:value-of select="concat($name-prefix, '-', local-name(.))"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="local-name(.)"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="text()" mode="flatten"/>
</xsl:stylesheet>

:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <PNode-node1-node1Child>data</PNode-node1-node1Child>
    <PNode-node1-node2Child>data</PNode-node1-node2Child>
    <SecondNode-node1-node1Child-child>data</SecondNode-node1-node1Child-child>
</root>
+1

node.

node, , .

#text, #text

0

All Articles