【问题标题】:How to get child nodes in XML::LibXML by node type?如何按节点类型获取 XML::LibXML 中的子节点?
【发布时间】:2014-10-12 10:18:24
【问题描述】:

我正在解析复杂的 XML 文档,其中一个部分可能如下所示:

<mds>
  <md>
    <value>
      <![CDATA[<?xml version="1.0" encoding="UTF-8"?><record>...</record>]]>
    </value>
  </md>
</mds>

当我解析 value 节点时,它实际上包含 3 个子节点,两个空节点和一个 cdata 节点。有没有办法轻松获取 cdata-node,比如

my @dcvalues = $dom->findnodes("//mds/md/value");
my @cdatanodes = $dcvalues[0]->find(<some xpath that only returns cdata nodes>);
my $cdataval = $cdatanodes[0]->textContent;

你明白了。 编辑:我知道我可以在这个例子中访问 c​​data

my $cdatanode = $dcvalues[0]->firstChild->nextSibling;

但是我会依赖 cdata 始终是第二个节点,我不确定。

【问题讨论】:

  • 您可以使用my @dcvalues = $dom-&gt;findnodes('//mds/md/value[2]') 访问第二个孩子。无需搞乱 DOM 调用。
  • 有人发布了很好的答案,现在它消失了,不知道为什么。他建议使用这样的 grep:my @cdataList = grep { $_->nodeType == XML_CDATA_SECTION_NODE} $dcValues[0]->getChildnodes;。以防万一有人需要类似的东西。
  • 在我发表评论纠正了他的 XPath 之后,他自己删除了它。我觉得他被冒犯了!声望达到或超过 10,000 的人仍然可以看到它。
  • 谢谢鲍罗丁。是的,我还注意到 xpath 的某些问题不太正确,但它对我来说仍然是一个有价值的答案......
  • 我想我会使用 grep /\S/, @nodes 来删除所有只包含空格的节点。请注意,您可以使用$_-&gt;isa('XML::LibXML::CDATASection'),它与$_-&gt;nodeType == XML_CDATA_SECTION_NODE 做同样的事情。在 XPath 中无法做到这一点,因为 CDATA 无法与普通文本节点区分开来 - 它只是转义麻烦字符的另一种方式。

标签: perl xml-parsing libxml2 cdata


【解决方案1】:

您需要no_blanks 解析器选项。像这样

use strict;
use warnings;
use 5.010;

use XML::LibXML;

my $xml = XML::LibXML->load_xml(string => <<END_XML, {no_blanks => 1});
<mds>
  <md>
    <value>
      <![CDATA[<?xml version="1.0" encoding="UTF-8"?><record>...</record>]]>
    </value>
  </md>
</mds>
END_XML


my @values = $xml->findnodes('//mds/md/value/text()');

say scalar @values;

say say $values[0]->textContent;

输出

1
<?xml version="1.0" encoding="UTF-8"?><record>...</record>

【讨论】:

  • 好一个。刚才还找到了另外一个: $cdatastr = $dom->findvalue("//mds/md/value");似乎工作得很好......感谢 no_blanks 选项。
  • @jackthehipster:好的。我很高兴您找到了适合您的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 2020-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多