如何使用xsl从xml节点获取CDATA ?

时间:2022-10-27 08:01:58

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

我正在尝试使用XSL获取XML节点的CDATA内容。节点当前是这样的:

<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.

提前谢谢。

5 个解决方案

#1


10  

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文件:

<?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.

我得到一个解析错误,因为id=1是无效的XML。

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

在属性值(id="1")周围加上引号,然后重新运行样式表,就得到输出:

This is sample text

这是示例文本

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

这是一个开始。基本上,只要把CDATA当作一个文本节点就可以了。

You said:

你说:

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

我找到了以下内容: ,然后获取CDATA:

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.

如果你使用的是value-of,那么这个方法也很好用。这里有一个例子,你的评论,使用值-而不是。但是请注意,CDATA - sec- elements只在输出端工作,这表明您希望将哪些输出XML元素打印为CDATA sections而不是普通的旧字符数据。它与获取数据没有任何关系。

<?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>

#2


1  

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

实现这一点的其他一些简单步骤;使用W3cschools编辑来试用。示例XML文件:

<?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 :

示例XSL文件:

<?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;
如何使用xsl从xml节点获取CDATA ?

最终结果;

#3


0  

For output CDATA sections:

对于输出CDATA节:

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

您必须使用xsl:output/@cdata- sec-元素。从http://www.w3.org/TR/xslt输出

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.

cdata- sec- elements属性包含一个用空格分隔的qname列表。使用在发生QName的xsl:output元素上有效的名称空间声明将每个QName扩展为一个扩展名;如果有一个默认的名称空间,它用于没有前缀的qname。扩展在将多个xsl:output元素合并到一个有效的xsl:output元素之前执行。如果文本节点的父节点的扩展名是列表的成员,那么文本节点应该作为CDATA部分输出。

Besides DOE, of course.

当然,除了能源部。

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

不能使用XPath选择CDATA节。据http://www.w3.org/TR/xpath/数据模型

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

从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.

CDATA部分中的每个字符都被视为字符数据。因此,< !源文档中的[CDATA[<]]>将被处理为<。两者都将导致在树中的文本节点中出现单个 <字符。因此,cdata部分被当作 被移除, <和&的每一个发生都被替换为<和,分别。< p>

#4


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.

然而,这并不是最干净的解决方案,特别是如果您需要在XSLT的各个部分实现此功能。此外,如果您的输入XML已经有CDATA(也就是说,您正在尝试保存CDATA),那么使用disable-output-escaping将不会工作,因为到那时XSLT引擎已经解析了CDATA,剩下的将是最终可能破坏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:

根据您使用XSLT的方式,可以使用外部/注入函数。这样做,您可以轻松地减少您编写的代码的数量,并最终得到一个更整洁的模板:

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

{XSLT}     
<title>
    <xsl:value-of select="CDataType:CDATAWrap(label)" disable-output-escaping="yes" />
</title>

#5


-1  

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

我尝试了各种组合然后得到了这个的解;

 <xsl:value-of select="/node/."/>

#1


10  

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文件:

<?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.

我得到一个解析错误,因为id=1是无效的XML。

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

在属性值(id="1")周围加上引号,然后重新运行样式表,就得到输出:

This is sample text

这是示例文本

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

这是一个开始。基本上,只要把CDATA当作一个文本节点就可以了。

You said:

你说:

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

我找到了以下内容: ,然后获取CDATA:

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.

如果你使用的是value-of,那么这个方法也很好用。这里有一个例子,你的评论,使用值-而不是。但是请注意,CDATA - sec- elements只在输出端工作,这表明您希望将哪些输出XML元素打印为CDATA sections而不是普通的旧字符数据。它与获取数据没有任何关系。

<?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>

#2


1  

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

实现这一点的其他一些简单步骤;使用W3cschools编辑来试用。示例XML文件:

<?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 :

示例XSL文件:

<?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;
如何使用xsl从xml节点获取CDATA ?

最终结果;

#3


0  

For output CDATA sections:

对于输出CDATA节:

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

您必须使用xsl:output/@cdata- sec-元素。从http://www.w3.org/TR/xslt输出

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.

cdata- sec- elements属性包含一个用空格分隔的qname列表。使用在发生QName的xsl:output元素上有效的名称空间声明将每个QName扩展为一个扩展名;如果有一个默认的名称空间,它用于没有前缀的qname。扩展在将多个xsl:output元素合并到一个有效的xsl:output元素之前执行。如果文本节点的父节点的扩展名是列表的成员,那么文本节点应该作为CDATA部分输出。

Besides DOE, of course.

当然,除了能源部。

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

不能使用XPath选择CDATA节。据http://www.w3.org/TR/xpath/数据模型

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

从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.

CDATA部分中的每个字符都被视为字符数据。因此,< !源文档中的[CDATA[<]]>将被处理为<。两者都将导致在树中的文本节点中出现单个 <字符。因此,cdata部分被当作 被移除, <和&的每一个发生都被替换为<和,分别。< p>

#4


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.

然而,这并不是最干净的解决方案,特别是如果您需要在XSLT的各个部分实现此功能。此外,如果您的输入XML已经有CDATA(也就是说,您正在尝试保存CDATA),那么使用disable-output-escaping将不会工作,因为到那时XSLT引擎已经解析了CDATA,剩下的将是最终可能破坏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:

根据您使用XSLT的方式,可以使用外部/注入函数。这样做,您可以轻松地减少您编写的代码的数量,并最终得到一个更整洁的模板:

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

{XSLT}     
<title>
    <xsl:value-of select="CDataType:CDATAWrap(label)" disable-output-escaping="yes" />
</title>

#5


-1  

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

我尝试了各种组合然后得到了这个的解;

 <xsl:value-of select="/node/."/>