来自textContent的Perl LibXML原始数据?

时间:2012-04-25 19:35:36

标签: perl libxml2

给出以下XML:

<?xml version="1.0" encoding="utf-8" ?> 
<Request>
    <form_submit>
        <form_submit id = 1424>
            <form_id>1424</form_id>
            <field1 id=’5’> <![CDATA[ test   ]]>   </field1>
            <field2 id=’6’> <![CDATA[ test2   ]]>   </field2>
        </form_submit>
    </form_submit>
</Request>

我正在尝试获取field1和field2元素的原始值。我正在使用以下代码:

foreach my $node ( $xml_request->findnodes('Request/*/*/*[@id]') )
{
    my $form_field_value = $node->textContent;
    print "Value:\"$form_field_value\"\n";
}

但输出是:

Value:" test   "
Value:" test2  "

如何使用所有特殊字符检索原始和原样的确切数据?所以输出是:

Value:" <![CDATA[ test   ]]>   "
Value:" <![CDATA[ test2   ]]>   "

谢谢。

2 个答案:

答案 0 :(得分:2)

不是libxml专家。 然而,这是我在使用你的xml和libxml之后想出来的。 CDATA是节点/部分,不是文本的一部分。 下面的代码深入一级,并为cdata子节点执行toString() 和其他节点的textContent。

foreach my $node ( $xml_request->findnodes('Request/*/*/*[@id]') )
{
    my $text;
    if($node->childNodes) {
        foreach my $child ($node->childNodes()) {
            if ($child->nodeType == XML::LibXML::XML_CDATA_SECTION_NODE) {
                $text .= $child->toString;
            } else {
                $text .= $child->textContent;
            }
        }
    } else {
        $text = $node->textContent;
    }
    print qq{"$text"\n};
}

将打印

" <![CDATA[ test   ]]>   "
" <![CDATA[ test2   ]]>   "

答案 1 :(得分:2)

您的示例数据是无效的XML,除非您将1424’5’’6’替换为"1424""5"和{{},否则不会解析1}}。

您已经要求提供文字内容,并且已经完全相同。要获得所需内容,您必须搜索"6"元素的 children 并在其上使用<fieldN>方法。

此代码显示了这个想法。请注意,toString之前和之后的空格(否则将显示为单独的文本节点)已使用对象构造函数上的CDATA选项消除。

keep_blanks => 0

<强>输出

use strict;
use warnings;

use XML::LibXML;

my $xml_request = XML::LibXML->load_xml(string => <<'END', keep_blanks => 0);
<?xml version="1.0" encoding="utf-8" ?> 
<Request>
  <form_submit>
    <form_submit id = "1424">
      <form_id>1424</form_id>
      <field1 id="5"> <![CDATA[ test   ]]>   </field1>
      <field2 id="6"> <![CDATA[ test2   ]]>   </field2>
    </form_submit>
  </form_submit>
</Request>
END

foreach my $node ( $xml_request->findnodes('//form_submit/*[@id]/text()') ) {
  my $form_field_value = $node->toString;
  print qq(Value: "$form_field_value"\n);
}

修改

ikegami评论说,问题中请求的输出包括CDATA部分周围的空白。我不知道这是否真的是要求的一部分,但这种编辑提供了一种方法。

使用XML::LibXML::Reader会更清楚,因为它有一个Value: "<![CDATA[ test ]]>" Value: "<![CDATA[ test2 ]]>" 方法(与JavaScript的readInnerXml相当),可以完全满足要求。相反,该程序必须序列化innerHTML个节点的所有子节点,并将它们与<fieldN>连接起来。

这是一个新的join循环。除foreach的构造外,程序的其余部分保持不变,$xml_request必须将keep_blanks选项设置为1或完全删除。

foreach my $node ( $xml_request->findnodes('//*[starts-with(name(),"field")][@id]') ) {
  my $form_field_value = join '', map $_->toString, $node->childNodes;
  print qq(Value: "$form_field_value"\n);
}

<强>输出

Value: " <![CDATA[ test   ]]>   "
Value: " <![CDATA[ test2   ]]>   "