如何防止LibXML prettyprint更改元素值?

时间:2014-11-11 09:26:23

标签: perl libxml2 pretty-print

请考虑以下代码段:

my $PRSR = XML::LibXML->new();
my $PP = XML::LibXML::PrettyPrint->new(indent_string => "  ");
my $tmRawData = <DATA>;
my $tmDOM = $PRSR->load_xml(string => $tmRawData);
my $hm="SHA-1";
say $tmDOM->findvalue('//checksum[checksumMethod="' . $hm .'"]/checksumValue');
my $prettyxml = $PP->pretty_print($tmDOM->documentElement())->toString();
say $tmDOM->findvalue('//checksum[checksumMethod="' . $hm .'"]/checksumValue');
say $prettyxml;
__DATA__
<checksum> <checksumMethod>SHA-1</checksumMethod> <checksumValue>56db195fc75e93509133193bfe5608eaeef2c471</checksumValue> </checksum>

第一个说将正确打印出哈希值。第二个说将打印一个空字符串。显然,pretty_print通过用空格填充它们来更改所有元素值,以便在打印时看起来很漂亮。我可以在xpath中使用“contains”来解决这个肮脏的方式,但那会很脏。

现在我的第一个(也是迄今为止唯一的)想法就是简单地复制DOM对象,以便pretty_print可以搞砸一个而不用另外一个,就像这样:

my $PRSR = XML::LibXML->new();
my $PP = XML::LibXML::PrettyPrint->new(indent_string => "  ");
my $tmRawData = <DATA>;
my $tmDOM = $PRSR->load_xml(string => $tmRawData);
my $hm="SHA-1";
say $tmDOM->findvalue('//checksum[checksumMethod="' . $hm .'"]/checksumValue');
my $tmDOM2 = $tmDOM;
my $prettyxml = $PP->pretty_print($tmDOM2->documentElement())->toString();
say $tmDOM->findvalue('//checksum[checksumMethod="' . $hm .'"]/checksumValue');
__DATA__
<checksum> <checksumMethod>SHA-1</checksumMethod> <checksumValue>56db195fc75e93509133193bfe5608eaeef2c471</checksumValue> </checksum>

但这会产生完全相同的结果。

  1. 问题:为什么不将tmDOM复制到另一个变量tmDOM2来解决这个问题?
  2. 问题:有没有办法阻止pretty_print搞乱元素值?

2 个答案:

答案 0 :(得分:1)

  

问题:为什么不将tmDOM复制到另一个变量tmDOM2来解决这个问题?

因为您正在复制参考。就像这样:

my $x = [ 1 .. 9 ];
my $y = $x;               # copy $x to $y to protect it from changes to $x
push @$x, 10;             # change $x
print "$_\n" for @$y;     # d'oh! we changed $y too
  

问题:有没有办法阻止pretty_print搞乱元素值?

阅读文档。特别是,搜索preserves_whitespace选项,它允许您告诉XML :: LibXML :: PrettyPrint保留特定元素中的空格。

答案 1 :(得分:1)

使用cloneNode方法获取同一DOM节点的新副本。

my $PP        = 'XML::LibXML::PrettyPrint'->new( indent_string => '  ' );
my $tmRawData = <DATA>;
my $tmDOM     = 'XML::LibXML'->load_xml( string => $tmRawData );
my $tmDOM2    = $tmDOM->cloneNode(1);                        # <--- HERE
my $hm        = 'SHA-1';
say '1: ', $tmDOM->findvalue("//checksum[checksumMethod='$hm']/checksumValue");
my $prettyxml = $PP->pretty_print($tmDOM->documentElement)->toString;
say '2: ', $tmDOM2->findvalue("//checksum[checksumMethod='$hm']/checksumValue");
say '3: ', $prettyxml;