给出以下XML片段:
<outline>
<node1 attribute1="value1" attribute2="value2">
text1
</node1>
</outline>
如何获得此输出?
outline
node1=text1
node1 attribute1=value1
node1 attribute2=value2
我查看了use XML::LibXML::Reader;
,但该模块似乎只提供对其名称引用的属性值的访问权限。并且如何首先获取属性名称列表?
答案 0 :(得分:5)
这样的事情可以帮助你。
从您的问题中不清楚<outline>
是否是数据的根元素,或者它是否隐藏在更大的文档中。它还不清楚你想要解决方案的一般程度 - 例如你想以这种方式转储整个文件吗?
无论如何,这个程序以一种相当简洁的方式从给定的XML输入生成您请求的输出。
use strict;
use warnings;
use 5.014; #' For /r non-destructive substitution mode
use XML::LibXML;
my $xml = XML::LibXML->load_xml(IO => \*DATA);
my ($node) = $xml->findnodes('//outline');
print $node->nodeName, "\n";
for my $child ($node->getChildrenByTagName('*')) {
my $name = $child->nodeName;
printf "%s=%s\n", $name, $child->textContent =~ s/\A\s+|\s+\z//gr;
for my $attr ($child->attributes) {
printf "%s %s=%s\n", $name, $attr->getName, $attr->getValue;
}
}
__DATA__
<outline>
<node1 attribute1="value1" attribute2="value2">
text1
</node1>
</outline>
<强>输出强>
outline
node1=text1
node1 attribute1=value1
node1 attribute2=value2
答案 1 :(得分:4)
您可以通过$e->findnodes( "./@*");
下面是一个解决方案,使用纯XML :: LibXML,而不是XML :: LibXML :: Reader,它可以处理您的测试数据。它可能对额外的空格和混合内容很敏感,因此在使用它之前在真实数据上进行测试。
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
my $dom= XML::LibXML->load_xml( IO => \*DATA);
my $e= $dom->findnodes( "//*");
foreach my $e (@$e)
{ print $e->nodeName;
# text needs to be trimmed or line returns show up in the output
my $text= $e->textContent;
$text=~s{^\s*}{};
$text=~s{\s*$}{};
if( ! $e->getChildrenByTagName( '*') && $text)
{ print "=$text"; }
print "\n";
my @attrs= $e->findnodes( "./@*");
# or, as suggested by Borodin below, $e->attributes
foreach my $attr (@attrs)
{ print $e->nodeName, " ", $attr->nodeName. "=", $attr->value, "\n"; }
}
__END__
<outline>
<node1 attribute1="value1" attribute2="value2">
text1
</node1>
</outline>