【问题标题】:How can I access CDATA as a node using XPath in Java?如何在 Java 中使用 XPath 作为节点访问 CDATA?
【发布时间】:2012-08-22 07:07:44
【问题描述】:

在以下 XML 上使用 this 在线 XPath 测试器

<a>foo <![CDATA[ MyCData]]>  baz</a>    

使用 XPath 表达式/a/text(),我得到了所有的文本

foo <![CDATA[ MyCData]]>  baz 

(结构为三个节点,正如我们使用 /a/text()[2] 所看到的,它返回 baz。)

但是,对于 javax.xml.xpath.XPath, CData 和最后一个文本节点完全 返回。我得到一个带有foo 的节点,而文本&lt;![CDATA[ MyCData]]&gt; baz 的其余部分不可用。不管 XPath 如何处理 XML 结构,如果我们根本无法访问节点就是一个 bug。

但是,如果我在 DocumentBuilderFactory 上设置 isCoalescing(true),它会将所有文本和 CData 节点连接为一个。我可能最终会使用它,但它会将 CData 转换为输出中的转义文本,这看起来很难看,即使标准允许它也是如此。此外,我希望能够将 CData 单独作为某种节点来处理,无论是“只是”一个文本节点,还是某种特殊类型的 CData 节点。

顺便说一下,如果 CData 是其父元素的 only 内容,前面没有空格或其他文本,普通的 text-content XPath 可以成功检索它,即使使用 isCoalescing 在其默认值 (false)。因此,我们看到 Java XPath 总是返回第一个,并且只返回第一个文本节点。

当我检查我的 DOM 文档的完整 DOM 树时,默认使用 isCoalescing,我发现 CData 部分表示为它自己的 cdata-section 类型节点em>,很好,但是如何在 XPath 中访问这个节点?

【问题讨论】:

  • 谢谢,但那是关于 XML inside CData。我只想要CData!在其他 XPath 引擎中,CData 只是一个文本节点,但在 Java 中不是,如上所述。

标签: java xpath cdata


【解决方案1】:

恐怕在线 XPath 测试仪弄错了。根据 XPath 数据模型,&lt;a&gt; 元素有一个文本节点子节点,其字符串值为"foo MyCDATA baz";没有第二个文本节点,因此对第二个文本节点的请求不应返回任何内容。

XPath 数据模型认为 CDATA 只是一种输入数据的便捷方式,以避免转义特殊字符; CDATA 的存在不会影响 XML 的含义或信息内容,因此它不会对应用程序可用。

【讨论】:

  • 好的,如果 Java XPath 返回单个节点 foo MyCData baz,那就太好了。但实际上,它返回单个节点 foo 而没有其他节点。
  • 显然 setCoalescing(true) 给出了您描述的结果。但是在合并为假的情况下,Java XPath 引擎会做什么?它似乎没有产生替代结构,而只是“放弃”除第一个节点以外的所有文本。
  • Saxon XPath 引擎为您提供包含所有数据的单个文本节点,无论 DOM 是否合并。试一试。 (更好的是,不要使用 DOM:切换到更好的树模型,例如 JDOM 或 XOM)。
  • "...无论 DOM 是否合并":我宁愿不将 CData 转换为输出中的转义文本,因为它看起来很难看,即使它是标准的。此外,我希望能够将 CData 单独作为某种节点来处理,无论是“只是”XPath 规范中的文本节点,还是某种特殊类型的节点。
  • 我告诉你 XPath 规范是怎么说的。您希望它说其他内容这一事实并不真正相关。
猜你喜欢
  • 2011-08-24
  • 2011-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多