【问题标题】:How to get CDATA from xml node using xsl ?如何使用 xsl 从 xml 节点获取 CDATA?
【发布时间】:2011-02-27 03:55:36
【问题描述】:

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

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

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

提前致谢。

【问题讨论】:

  • 尝试使用该模板。但它没有返回任何值。
  • 实际上,我从各种资源中发现了类似的东西; 然后去获取CDATA; 它什么也不返回。
  • @Vijay:CDATA 是一种编码人工制品(以避免大量实体),它们不会出现在 XML 信息集中,因此通常不会出现在 API 和工具中。
  • 我编辑了你的问题:我以为你试图匹配 only 包含 CDATA 部分的 xml 节点。
  • 编辑问题以使 CDATA 有效;必须有 2 个右括号。

标签: xml xslt cdata


【解决方案1】:

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

<?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 视为文本节点即可。

你说:

我发现了类似的东西:
&lt;xsl:output cdata-section-elements="text"/&gt;
然后获取 CDATA:
&lt;xsl:value-of select="node" /&gt;

如果您也使用value-of,这种方法也可以正常工作。这将是您评论中的一个示例,改用value-of。但请注意,cdata-section-elements 仅在输出端有效,指示您希望将哪些 output 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>

【讨论】:

  • 嗨欧文,好的,谢谢你的回复。实际上,我希望 CDATA 在 if 条件下。有一些条件取决于它们,我需要将此 CDATA 值分配给 Label 控件。
  • 发布一个关于您正在尝试做的事情以及您希望自己的价值去向何方的 sn-p 怎么样?
【解决方案2】:

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

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

【讨论】:

  • 在标记任何东西之前,我要求大家提供理由。这样对我有帮助。
  • 您的问题有两个答案。这非常令人困惑,特别是因为您已经接受了另一个更长(且分散注意力)的答案。如果您将两者合二为一,删除无贡献的位,我将不胜感激。
【解决方案3】:

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


最终结果是;

【讨论】:

  • 在标记任何东西之前,我要求大家提供理由。这样对我有帮助。
【解决方案4】:

对于输出 CDATA 部分:

你必须使用xsl:output/@cdata-section-elements。来自http://www.w3.org/TR/xslt#output

cdata-section-elements 属性 包含一个空格分隔的列表 的 QNames。每个 QName 都扩展为 使用命名空间的扩展名称 生效的声明 xsl:QName 所在的输出元素 发生;如果有默认 命名空间,它用于 QNames 没有前缀。扩展是 在合并之前执行 多个 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 节中的每个字符 被视为字符数据。因此, 源文档中的&lt;![CDATA[&lt;]]&gt; 将与 <![CDATA[ 和 ]]&gt; 被删除,每个 &amp;lt; 和 &amp;amp; 的出现被替换为 分别为&amp;lt; 和&amp;amp;。

【讨论】:

    【解决方案5】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-07
      • 1970-01-01
      • 1970-01-01
      • 2012-12-20
      • 2019-07-07
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      相关资源
      最近更新 更多