Search code examples
xsltcdata

Extract text inside cdata tag using XSLT


I have the following XML with a cdata tag that I would like to extract the text from?

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<cus:TestData xmlns:cus="http://test.namespace.com/data">
<![CDATA[testValue]]></cus:TestData >

How can I achieve this in XSLT?

I was briefly trying with the following

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text"/>
    <xsl:template match="/">
        "<xsl:value-of select="/*/Name"/>"
    </xsl:template>
</xsl:stylesheet>

But it doesn't seem to be working

Also the XML doesn't also have the same prefix or namespace, it changes


Solution

  • This is not really an issue with CData. Your XSLT is currently looking for an element called Name, under the root element, which does not exist in your XML. If your XML source is the one you are actually using, you can just do this...

    <xsl:value-of select="/*"/>
    

    But supposing your XML looked like this...

    <cus:TestData xmlns:cus="http://test.namespace.com/data">
       <cus:Name><![CDATA[testValue]]></cus:Name>
    </cus:TestData>
    

    Then, you would need to account for the namespace in your XSLT, as Name is in a namespace in your XML, but your XSLT is currently looking for a Name element in no namespace.

    Something like this would do:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:c="http://test.namespace.com/data">
        <xsl:output method="text"/>
        <xsl:template match="/">
          "<xsl:value-of select="/*/c:Name"/>"
        </xsl:template>
    </xsl:stylesheet>
    

    Note, the prefixes don't need to match, but the namespace URI does.

    If the namespace URI could actually vary, you could do something like this instead...

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>
        <xsl:template match="/">
          "<xsl:value-of select="/*/*[local-name() = 'Name']"/>"
        </xsl:template>
    </xsl:stylesheet>