【问题标题】:How do i read individual xml nodes from a node that contains both CDATA and xml如何从包含 CDATA 和 xml 的节点中读取单个 xml 节点
【发布时间】:2012-10-08 23:12:02
【问题描述】:

我有问题。我有几个 xml 文件,其中随机包含带有 CDATA 和 reqular xml 节点的节点。我需要读取这些节点的内容,但不确定如何确定该节点是普通 xml 节点、CDATA 节点还是包含两者混合的节点,其中开头和结尾的 CDATA 部分可能包含任何事物。 (如果有帮助,我正在使用 xPath 来引用我的节点)

用于检索节点文本内容的行:

contentObj.text = contentNode.selectSingleNode("./text").text;

导致问题的xml示例:

<text>
     <![CDATA[<P align=center>&nbsp;</P>
          <P align=center>]]>
     <media identifier="005896523">
          <label>
               <![CDATA[NOTE]]>
          </label>
          <description>
               <![CDATA[Image for NOTE]]>
          </description>
          <comments>Update Required</comments>
     </media>
    <![CDATA[</P>
       <P>&nbsp;</P>
       <P align=left>&nbsp;</P>]]>
</text>

【问题讨论】:

  • CDATA 只是另一种引用文本的方式。它始终是文本节点的一部分。
  • 我知道 CDATA 是透明的,然后我调用 node.text,但是在上面的 xml 中,如果我调用 node.text,我不仅得到 cdata 中包含的前 2 行,还得到文本任何非 CDATA 节点的值。我需要能够在示例中分离 CDATA XML CDATA 混合物,或者至少能够识别节点包含 CDATA,因为它可能不在完整 XML 结构的其他迭代中。
  • 您无法区分 CDATA 部分及其周围的文本。如果它们之间有什么(一个元素),你可以。您将哪个节点称为 node.text?请注意,如果有多个文本节点,XPath 可以返回一个节点列表。
  • 我使用以下行来读取 节点的内容。 contentObj.text = contentNode.selectSingleNode("./text").text;它检索封装在文本节点的 CDATA 部分中的文本,但是由于某种未知原因,同一节点内还有其他 xml 节点,但是它们不在 cdata 部分内
  • (./text/text())[1](./text/text())[2] 等返回什么?

标签: javascript xml xpath cdata xmldom


【解决方案1】:

当你说

contentNode.selectSingleNode("./text")

这当然会返回&lt;text&gt; 元素节点;但是当你然后要求

.text

它的属性,你要的是整个 &lt;text&gt; 元素的文本内容,它是其所有后代文本节点的值的串联。

如果要选择单个文本节点,请尝试

contentNode.selectSingleNode("./text/text()[1]").text;

即选择&lt;text&gt; 元素的第一个文本节点子节点,然后检索其文本属性。在您的示例中,这应该会给您"&lt;P align=center&gt;&amp;nbsp;&lt;/P&gt; &lt;P align=center&gt;"(作为未解析的文本,而不是 XML 树)。

为了区分 CDATA 和非 CDATA,您必须使用 XPath,它的设计目的不是能够区分它们。另一方面,XML DOM 可以,至少在某些实现中是可以的。所以你可以试试

var children = contentNode.selectNodes("./text/node()");

这将选择&lt;text&gt; 元素的所有子元素中的nodeList,包括文本节点、元素节点和可能的CDATA 节点。遍历children 中的节点并检查它们的nodeType 属性以查看它是NODE_CDATA_SECTIONNODE_TEXT 还是其他。

让我们知道进展如何,以及您是否需要进一步的帮助。

编辑

我假设你接受了这个答案,你能够让事情正常进行,我很高兴你能够做到。

但是,我不想在不强调 @choroba 所暗示的警告的情况下放弃这一点:CDATA 包装器(围绕一段文本)对大多数 XML 工具是不可见的(尽管文本内容是可见的)。 XML 数据模型(非正式地描述为here)对CDATA 部分一无所知。 XML Infoset 的标准explicitly omits 有关 CDATA 标记部分边界的信息。

因此,虽然您这次“走运了”,因为您使用的是确实提供有关 CDATA 部分信息的 XML DOM,但依赖该信息来编码重要数据是违反 XML 的精神的(因此是不明智的)在 XML 中。因此,您最好以其他方式对该信息进行编码。否则,如果您需要对数据使用其他 XML 工具,您可能会陷入困境。

我认为您在此处尝试提取的重要信息是 CDATA 部分中的文本是转义标记。例如。它是不应该(或不能)成为 XML 树的一部分的 HTML 标记。因此,您可以通过使用自定义元素围绕每个标识来编码该标识:

<text>
     <escaped><![CDATA[<P align=center>&nbsp;</P>
          <P align=center>]]></escaped>
     <media identifier="005896523">
     ...

那么,为了在未来找到这些部分,您所要做的就是查找名为 &lt;escaped&gt; 的元素,这对于任何 XML 工具来说都是一项简单而自然的任务。

我不知道这些 XML 文件的设计是否在您的控制之下。如果没有,您至少应该可以选择向设计师发送反馈。如果不精通 XML 事物的设计人员犯了设计错误,那么了解它符合他们的最大利益,以便他们能够纠正它,或者至少在未来的设计中避免同样的错误。如果您在一个指挥链下工作,并且 XML 的设计者在不同的部门,则反馈的适当途径可能是通过您的主管。了解他们是否正在制作不可移植的 XML 设计符合该部门的最大利益。

【讨论】:

  • 在我创建的每个 XML 文档中,cdata 不与任何其他节点共享相同的节点。必须喜欢与别人创造的东西一起工作。可悲的是,我正在解析的创建原始数据导出(openXML 规范)的软件来自一个成熟的组织,正如我来找出“混乱”数据导出的方式以便从咨询中产生额外收入一样。
  • 感谢您的指导。由于我仍在学习某些编程实践,因此像您这样的帖子可确保我不会学习不良实践。我只希望当我变得更好时,我能够像你一样指导其他人来回馈社区。​​span>
  • @Reahreic:感谢您的 cmets。你能给我一个指向相关 OpenXML 规范的指针吗?我想验证 CDATA 部分是否真的很重要,而不是仅查找文本节点是否可以解决问题。
  • 我无法告诉您他们正在导出到哪个开放 XML 规范,只是它们指的是使用开放 xml 将数据导入和导出应用程序的能力。
猜你喜欢
  • 2011-02-27
  • 2013-08-17
  • 2017-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-14
  • 2011-03-09
相关资源
最近更新 更多