How to get CDATA from xml node using xsl ?
Asked Answered
H

5

7

I am trying to get the CDATA content of an XML node using XSL. The node currently looks like this:

<node id="1" text="Book Information" ><![CDATA[This is sample text]]></node>

I need the This is sample text piece. Does anyone have any idea about this?

Thanks in advance.

Hamelin answered 3/6, 2010 at 6:2 Comment(5)
tried with the template. But it is not returning any value.Hamelin
Actually, from various resources I found something like; <xsl:output cdata-section-elements="text"/> and then to fetch CDATA; <xsl:value-of select="node" /> It returns nothing.Hamelin
@Vijay: CDATA is an encoding artefact (to avoid lots of entities), they don't show up in the XML infoset and thus are usually not present in APIs and tools.Washrag
I edited your question: I thought you were trying to match only xml nodes that contain CDATA sections.Staats
Edited question to make CDATA valid; there must be 2 close brackets.Lasandralasater
H
1

Some other easy steps to achieve this;
Used W3cschools editor to try out.
Sample XML File :

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<catalog>
    <cd>
        <disk id="title"><![CDATA[Sample xml]]></disk >
        <disk id="artist"><![CDATA[Vijay]]></disk >
    </cd>
</catalog>


Sample XSL file :

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Title</th>
        <th>Artist</th>
      </tr>
<xsl:for-each select="catalog/cd">

      <tr>
       <td><xsl:value-of select="/catalog/cd/disk[@id='title']"/></td>
       <td><xsl:value-of select="/catalog/cd/disk[@id='artist']"/></td>
       </tr>
</xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>


Final result is;
alt text

Hamelin answered 1/11, 2010 at 6:47 Comment(1)
before marking anything -ve, I request you all to provide reason. So that it ll be helpfull for me.Hamelin
S
12

Well, if I use this stylesheet:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>
  <xsl:template match="node/text()">
    <xsl:copy/>
  </xsl:template>
</xsl:stylesheet>

on this XML file:

<?xml version="1.0" encoding="utf-8"?>
<node id=1 text="Book Information" ><![CDATA[This is sample text]]></node>

I get a parse error, because id=1 is invalid XML.

Putting quotes around the attribute value (id="1") and rerunning the stylesheet, I get as output:

This is sample text

So there's a start. Basically, just treat the CDATA as a text node and you're on your way.

You said:

I found something like:
<xsl:output cdata-section-elements="text"/>
and then to fetch CDATA:
<xsl:value-of select="node" />

This approach works just fine if you're using value-of as well. Here would be an example along the lines of your comment, using value-of instead. Note, though, that cdata-section-elements only works on the output side, indicating which output XML elements you want to print as CDATA sections instead of plain old character data. It doesn't have anything to do with fetching the data.

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output cdata-section-elements="foo"/>
  <xsl:template match="/">
    <foo>
      <xsl:value-of select="node"/>
    </foo>
  </xsl:template>
</xsl:stylesheet>

prints out

<?xml version="1.0"?>
<foo><![CDATA[This is sample text]]></foo>
Supermundane answered 3/6, 2010 at 6:21 Comment(2)
Hi Owen, Well, thanks for your reply. Actually, I want CDATA under if condition. There are certain conditions depending upon them, I need assign this CDATA value to a Label control.Hamelin
How about posting a snippet of what you're trying to do and where you want your value to go?Supermundane
H
1

Some other easy steps to achieve this;
Used W3cschools editor to try out.
Sample XML File :

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<catalog>
    <cd>
        <disk id="title"><![CDATA[Sample xml]]></disk >
        <disk id="artist"><![CDATA[Vijay]]></disk >
    </cd>
</catalog>


Sample XSL file :

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
  <html>
  <body>
    <h2>My CD Collection</h2>
    <table border="1">
      <tr bgcolor="#9acd32">
        <th>Title</th>
        <th>Artist</th>
      </tr>
<xsl:for-each select="catalog/cd">

      <tr>
       <td><xsl:value-of select="/catalog/cd/disk[@id='title']"/></td>
       <td><xsl:value-of select="/catalog/cd/disk[@id='artist']"/></td>
       </tr>
</xsl:for-each>
    </table>
  </body>
  </html>
</xsl:template>
</xsl:stylesheet>


Final result is;
alt text

Hamelin answered 1/11, 2010 at 6:47 Comment(1)
before marking anything -ve, I request you all to provide reason. So that it ll be helpfull for me.Hamelin
D
0

For output CDATA sections:

You have to use xsl:output/@cdata-section-elements. From http://www.w3.org/TR/xslt#output

The cdata-section-elements attribute contains a whitespace-separated list of QNames. Each QName is expanded into an expanded-name using the namespace declarations in effect on the xsl:output element in which the QName occurs; if there is a default namespace, it is used for QNames that do not have a prefix. The expansion is performed before the merging of multiple xsl:output elements into a single effective xsl:output element. If the expanded-name of the parent of a text node is a member of the list, then the text node should be output as a CDATA section.

Besides DOE, of course.

You can't select CDATA sections with XPath. According to http://www.w3.org/TR/xpath/#data-model

There are seven types of node:

  • root nodes

  • element nodes

  • text nodes

  • attribute nodes

  • namespace nodes

  • processing instruction nodes

  • comment nodes

And from http://www.w3.org/TR/xpath/#section-Text-Nodes

Each character within a CDATA section is treated as character data. Thus, <![CDATA[<]]> in the source document will treated the same as <. Both will result in a single < character in a text node in the tree. Thus, a CDATA section is treated as if the <![CDATA[ and ]]> were removed and every occurrence of < and & were replaced by &lt; and &amp; respectively.

Demotic answered 1/11, 2010 at 15:17 Comment(0)
M
0

The only solution I've found on the web that works is this -

{XSLT}    
<title>
    <xsl:text disable-output-escaping="yes"><![CDATA[ <![CDATA[  ]]></xsl:text>
    <xsl:value-of select="label" disable-output-escaping="yes"/>
    <xsl:text disable-output-escaping="yes"><![CDATA[]]]]><![CDATA[>]]></xsl:text>
</title>

However, this isn't the cleanest of solutions especially if you need to implement this in various parts of your XSLT. Also, if your input XML already has the CDATA (i.e. you are attempting to preserve CDATA) using disable-output-escaping won't work since by that time the CDATA has already been parsed by the XSLT engine and all that'll be left is the content which can end up breaking the xml.

Here's my solution -

Depending on how you're using XSLT, it is possible to use external/injected functions. Doing that you can easily minimise the amount of code you are writing and end up with a much cleaner looking template:

{C#}
public string CDATAWrap(string data)
{
    return "<![CDATA[" + data + "]]>";
}

{XSLT}     
<title>
    <xsl:value-of select="CDataType:CDATAWrap(label)" disable-output-escaping="yes" />
</title>
Mistakable answered 18/10, 2016 at 9:44 Comment(0)
H
-1

I tried with various combinations and got the solution for this;

 <xsl:value-of select="/node/."/>
Hamelin answered 24/6, 2010 at 10:13 Comment(2)
before marking anything -ve, I request you all to provide reason. So that it ll be helpfull for me.Hamelin
You have two answers to your question. This is very confusing, specially because you have already accepted your other much longer (and distracting) answer. I'd appreciate if you combine both into one, removing the not-contributing bits.Staats

© 2022 - 2024 — McMap. All rights reserved.