Ives
Ives

Reputation: 39

Question on XSLT to eliminate parent node where child is in CDATA section

I have an original XML message which looks like below.

<Message>
    <Header>
        <MsgVerNo>1.0</MsgVerNo>
        <SourceId>XXX</SourceId>
        <MsgRefNo>1234567890</MsgRefNo>
        <LoginId>007</LoginId>
    </Header>
    <Body>
        <![CDATA[<txn>
<id>1234567</id>
<name>XXXX</name>
        </txn>]]>
    </Body>
</Message>

I wish to transform it as below. and should be removed while child nodes should be remained. In addition, CData which wrap should be removed as well.

<Message>
    <MsgVerNo>1.0</MsgVerNo>
    <SourceId>XXX</SourceId>
    <MsgRefNo>1234567890</MsgRefNo>
    <LoginId>007</LoginId>
    <txn>
        <record>
            <id>1234567</id>
            <name>XXXX</name>
        </record>
    </txn>
</Message>

I tried to use below XSLT. But the output is not desired.

<xsl:stylesheet version="2.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="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Header">
        <xsl:copy-of select="node()"/>
    </xsl:template>
    <xsl:template match="Body">
        <xsl:copy-of select="node()"/>
    </xsl:template>
</xsl:stylesheet>

Output

<Message>
<MsgVerNo>1.0</MsgVerNo>
<SourceId>XXX</SourceId>
<MsgRefNo>1234567890</MsgRefNo>
<LoginId>007</LoginId>
    &lt;txn&gt;
&lt;id&gt;1234567&lt;/id&gt;
&lt;name&gt;XXXX&lt;/name&gt;
    &lt;/txn&gt;
</Message>

I have no luck so far. Any help from expert please. Thanks.

Upvotes: 2

Views: 122

Answers (1)

ophychius
ophychius

Reputation: 2653

The CDATA element means that the data in between will not be interpreted as XML by your parse. This is specifically the purpose of CDATA. You can send character data, including < > without the parser trying to interpret it and potentially failing.

For all intents and purposes your Body node just contains text. You can read it as text and even strip the CDATA tag, however that still leaves you with text that looks like XML instead of something that is interpreted as XML.

You could use the following to get the contents, however if you wanted to further parse the contents of the body element you would have to pass it on to another XSLT for example.

<xsl:stylesheet version="2.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="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="Header">
        <xsl:copy-of select="node()"/>
    </xsl:template>
    <xsl:template match="Body">
        <xsl:value-of select="." disable-output-escaping="yes"/>
    </xsl:template>
</xsl:stylesheet>

Upvotes: 2

Related Questions