如何使用 xsl 从 xml 节点获取 CDATA?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2963633/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get CDATA from xml node using xsl ?
提问by Vijay Balkawade
I am trying to get the CDATAcontent of an XML node using XSL. The
node currently looks like this:
我正在尝试CDATA使用 XSL获取XML 节点的内容。该节点目前看起来像这样:
<node id="1" text="Book Information" ><![CDATA[This is sample text]]></node>
I need the This is sample textpiece. Does anyone have any idea about this?
我需要This is sample text那块。有没有人对此有任何想法?
Thanks in advance.
提前致谢。
采纳答案by Vijay Balkawade
Some other easy steps to achieve this;
Used W3cschoolseditor 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;

最终结果是;

回答by Owen S.
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=1is invalid XML.
我收到解析错误,因为id=1XML 无效。
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" />
我找到了类似的东西:
<xsl:output cdata-section-elements="text"/>
然后获取 CDATA:<xsl:value-of select="node" />
This approach works just fine if you're using value-ofas well. Here would be an example along the lines of your comment, using value-ofinstead. Note, though, that cdata-section-elementsonly works on the output side, indicating which outputXML elements you want to print as CDATA sections instead of plain old character data. It doesn't have anything to do with fetchingthe data.
如果您也在使用这种方法,则效果value-of很好。这将是您的评论中的一个示例,value-of而是使用。但是请注意,这cdata-section-elements仅适用于输出端,指示您希望将哪些输出XML 元素打印为 CDATA 部分而不是普通的旧字符数据。它与获取数据没有任何关系。
<?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>
回答by Vijay Balkawade
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-section-elements. 来自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.
cdata-section-elements 属性包含一个以空格分隔的 QName 列表。使用对出现 QName 的 xsl:output 元素有效的命名空间声明,将每个 QName 扩展为扩展名称;如果存在默认命名空间,则它用于没有前缀的 QName。扩展是在将多个 xsl:output 元素合并为单个有效 xsl:output 元素之前执行的。如果文本节点的父节点的扩展名是列表的成员,则文本节点应作为 CDATA 部分输出。
Besides DOE, of course.
当然,除了DOE。
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/#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
来自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<and&respectively.
CDATA 部分中的每个字符都被视为字符数据。因此,
<![CDATA[<]]>在源文档中将被视为 <。两者都将导致树中文本节点中的单个 < 字符。因此,CDATA 部分被视为<![CDATA[和]]>被删除,并且每次出现<和&都分别被<和替换&。
回答by Zizo47
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),则使用禁用输出转义将不起作用,因为到那时 CDATA 已经被 XSLT 引擎解析,所有这些都将被留下是最终会破坏 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>
回答by Vijay Balkawade
I tried with various combinations and got the solution for this;
我尝试了各种组合并得到了解决方案;
<xsl:value-of select="/node/."/>

