拥有以下内容:
perl -MXML::LibXML::Simple -MData::Dumper -E '$h=XMLin("<some><bubu>string</bubu></some>");say Dumper $h'
被解析为:
$VAR1 = {
'bubu' => 'string'
};
但是
perl -MXML::LibXML::Simple -MData::Dumper -E '$h=XMLin("<some><bubu/></some>"); say Dumper $h'
或
perl -MXML::LibXML::Simple -MData::Dumper -E '$h=XMLin("<some><bubu></bubu></some>");say Dumper $h'
打印:
$VAR1 = {
'bubu' => {}
};
可以获得
$VAR1 = {
'bubu' => ""
};
与其他字符串值保持一致吗?
问题背后的真实代码如下:
package Something {
use Moose;
has 'bar' => (is => 'ro', isa => 'Str');
has 'baz' => (is => 'ro', isa => 'Str');
}
use 5.014;
use warnings;
use XML::LibXML::Simple;
my $xml = do {local $/, <DATA>};
my $hr = XMLin($xml);
for my $node( @{$hr->{node}} ) {
my $obj = Something->new($node);
}
__DATA__
<root>
<node>
<bar>bar1</bar>
<baz>baz1</baz>
</node>
<node>
<bar>bar2</bar>
<baz/>
</node>
</root>
以
消亡Attribute (baz) does not pass the type constraint because: Validation failed for 'Str' with value HASH(0x7f91a4a92450) at /opt/anyenv/envs/plenv/versions/5.24.0/lib/perl5/site_perl/5.24.0/darwin-2level/Moose/Object.pm line 24
Moose::Object::new('Something', 'HASH(0x7f91a3f3d430)') called at l line 28
因此我需要
baz
视为{}
而不是''
Something
添加一些强制,以强制任何空的hashref {}
清空字符串''
。有什么想法吗?
所以,结果。接受的答案仍然是因为它给出了上述问题的答案。
但必须说,在研究了新的(非常复杂的)模块XML::Twig +学习XPath
的基础知识3天后,我得到了一个更清晰的解决方案更好的XMLIn
解决方案。
在XMLIn
我需要重新组织got hashref,因为只需要很少的元素并且具有精确定义的结构。 (构造函数可接受)。这样的重组(删除不需要的成员,将更深的hashref值移到arrayrefs等)在perl中是 easy ,但是代码不好并且需要处理上面的问题。
使用XML::Twig(以及此处的2个后续问题)结果比XMLIn更清晰,更易读,更强更短。真的是更好地牺牲一些时间和学习{至少基础知识'XPath
等......
答案 0 :(得分:2)
XML :: LibXML :: Simple似乎没有启用此行为的选项。
XML :: Simple确实如此;将SuppressEmpty
设置为空字符串,以将空节点解析为字符串而不是容器:
# perl -MXML::Simple -MData::Dumper \
-E '$h=XMLin("<some><bubu></bubu></some>", SuppressEmpty => ""); say Dumper $h'
$VAR1 = {
'bubu' => ''
};
答案 1 :(得分:1)
您可以使用Data::Find
模块遍历哈希,并查找空哈希引用的路径。然后,您可以使用eval
将空哈希引用替换为空字符串。这是一个例子:
use strict;
use warnings;
use XML::LibXML::Simple;
use Data::Dumper;
use Data::Find qw/ diter /;
my $xml = <<XML;
<root>
<node>
<bar>bar1</bar>
<baz>baz1</baz>
</node>
<node>
<bar>bar2</bar>
<baz/>
</node>
</root>
XML
my $h = XMLin($xml);
my $iter = diter $h, sub {
my $v = shift;
defined $v and ref($v) eq "HASH" and !(keys %{ $v });
};
while (my $path = $iter->() )
{
eval "\$h->$path = ''";
}
print Dumper($h);
答案 2 :(得分:1)
首先关闭:Why is XML::Simple "Discouraged"?
XML::Simple
不会让事情变得更容易,也会让事情变得更难。我会提倡XML::Twig
或XML::LibXML
。在XML::Twig
中获取节点的“值”完全符合您的预期:
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig -> parse ( \*DATA );
foreach my $node ( $twig -> findnodes('//node/*') ) {
print $node -> tag, " => \"", $node -> text,"\"\n";
}
__DATA__
<root>
<node>
<bar>bar1</bar>
<baz>baz1</baz>
</node>
<node>
<bar>bar2</bar>
<baz/>
</node>
</root>
给出:
bar => "bar1"
baz => "baz1"
bar => "bar2"
baz => ""
您可以将其传递给构造函数。