7

我正在尝试CDATA使用 XSL 获取 XML 节点的内容。该节点当前如下所示:

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

我需要This is sample text那块。有人对此有任何想法吗?

提前致谢。

4

5 回答 5

10

好吧,如果我使用这个样式表:

<?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=1XML 无效。

在属性值 ( ) 周围加上引号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>
于 2010-06-03T06:21:06.053 回答
1

实现这一目标的其他一些简单步骤;
使用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>


最终结果是;
替代文字

于 2010-11-01T06:47:09.583 回答
0

对于输出 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[]]>已被删除,并且每次出现的<&都被分别替换为 &lt;&amp;

于 2010-11-01T15:17:50.650 回答
0

我在网上找到的唯一可行的解​​决方案是 -

{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>
于 2016-10-18T09:44:37.667 回答
-1

我尝试了各种组合并得到了解决方案;

 <xsl:value-of select="/node/."/>
于 2010-06-24T10:13:29.137 回答