给出以下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 ]]> "
谢谢。
答案 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 ]]> "