我正在尝试CDATA
使用 XSL 获取 XML 节点的内容。该节点当前如下所示:
<node id="1" text="Book Information" ><![CDATA[This is sample text]]></node>
我需要This is sample text
那块。有人对此有任何想法吗?
提前致谢。
好吧,如果我使用这个样式表:
<?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>
在这个 XML 文件上:
<?xml version="1.0" encoding="utf-8"?>
<node id=1 text="Book Information" ><![CDATA[This is sample text]]></node>
我收到一个解析错误,因为id=1
XML 无效。
在属性值 ( ) 周围加上引号id="1"
并重新运行样式表,我得到输出:
这是示例文本
所以有一个开始。基本上,只需将 CDATA 视为文本节点即可。
你说:
我发现了类似的东西:
<xsl:output cdata-section-elements="text"/>
然后获取 CDATA:
<xsl:value-of select="node" />
如果您也使用这种方法,它也可以正常工作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>
打印出来
<?xml version="1.0"?>
<foo><![CDATA[This is sample text]]></foo>
实现这一目标的其他一些简单步骤;
使用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>
示例 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>
最终结果是;
对于输出 CDATA 部分:
你必须使用xsl:output/@cdata-section-elements
. 来自http://www.w3.org/TR/xslt#output
cdata-section-elements 属性包含一个以空格分隔的 QName 列表。每个 QName 都使用在 QName 出现的 xsl:output 元素上有效的命名空间声明扩展为扩展名称;如果有默认命名空间,它用于没有前缀的 QName。在将多个 xsl:output 元素合并为单个有效 xsl:output 元素之前执行扩展。如果文本节点的父节点的扩展名称是列表的成员,则文本节点应作为 CDATA 部分输出。
当然,除了DOE。
您不能使用 XPath 选择 CDATA 部分。根据http://www.w3.org/TR/xpath/#data-model
有七种类型的节点:
根节点
元素节点
文本节点
属性节点
命名空间节点
处理指令节点
评论节点
并来自http://www.w3.org/TR/xpath/#section-Text-Nodes
CDATA 部分中的每个字符都被视为字符数据。因此,
<![CDATA[<]]>
在源文档中将被视为<。两者都会在树的文本节点中产生一个 < 字符。因此,CDATA 部分被视为好像<![CDATA[
和]]>
已被删除,并且每次出现的<
和&
都被分别替换为<
和&
。
我在网上找到的唯一可行的解决方案是 -
{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>
然而,这并不是最干净的解决方案,尤其是当您需要在 XSLT 的各个部分实现它时。此外,如果您的输入 XML 已经具有 CDATA(即您正试图保留 CDATA),则使用 disable-output-escaping 将不起作用,因为到那时 CDATA 已经被 XSLT 引擎解析,所有这些都将被留下是最终会破坏 xml 的内容。
这是我的解决方案-
根据您使用 XSLT 的方式,可以使用外部/注入函数。这样做,您可以轻松地最小化您正在编写的代码量,并最终得到一个看起来更干净的模板:
{C#}
public string CDATAWrap(string data)
{
return "<![CDATA[" + data + "]]>";
}
{XSLT}
<title>
<xsl:value-of select="CDataType:CDATAWrap(label)" disable-output-escaping="yes" />
</title>
我尝试了各种组合并得到了解决方案;
<xsl:value-of select="/node/."/>