输入XML数据与输出XML格式不匹配

时间:2012-10-29 09:19:09

标签: xml perl

输入XML

<?xml version="1.0" encoding="utf-8"?>
<!--00/00/0000 12:35:25 AM-->
<Physical xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
  <Pro managementID="22000020">
    <Identification Type="XXXXX" >          
      <Address>
        <Data>test</Data>        
      </Address>
      <Phone>
        <Number>0000</Number>
      </Phone>
      <Email>test@com</Email>
    </Identification>       
  </Pro>
</Physical>

脚本:

我正在尝试更改标记的值并将其余内容打印到新的输出xml文件

use strict;
use warnings;
use XML::Simple;
use Data::Dumper;     

  my $xml = XML::Simple->new(ForceContent => 1,);
  my $xmlData = $xml->XMLin('input.xml') or die$!;     

  print Dumper (\$xmlData);

  foreach my $xmlKey ( keys %{$xmlData} ){
   if ( $xmlKey =~ m/Pro/){
       print ${$xmlData}{$xmlKey}{Identification}{Address}{Data}="hello";
    }
  }

XMLout(
    $xmlData,
    KeepRoot => 1,
    NoAttr => 0,
    OutputFile => $xml_out,
);

Outout XML:

<opt xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Pro managementID="22000020">
     <Identification Type="XXXXX">
      <Address Data="hello" />
      <Email>test@com</Email>
      <Phone name="Number">0000</Phone>
    </Identification>
  </Pro>
</opt>

我可以更改该值,但是当我尝试将数据写入输出时,格式已经更改。任何人都可以指导我获取相同的输入数据,并将更改后的值作为输出。

5 个答案:

答案 0 :(得分:4)

以这种方式使用XML :: LibXML:

#!/usr/bin/perl
use strict;
use warnings;

use XML::LibXML;

my $input;
while(<>) {
    $input .= $_;
}
my $xml_doc = XML::LibXML->load_xml(string => $input);
my $xpath_ctx = new XML::LibXML::XPathContext($xml_doc);
$xpath_ctx->find("/Physical/Pro/Identification/Address/Data")->get_node(0)->firstChild()->setData("hello");
my $xml_data = $xpath_ctx->find("/")->get_node(0)->toString(1);

print $xml_data;

XML :: LibXML更快,在XPath的帮助下,$xml_doc的操作更容易。

您可以找到更多信息here

答案 1 :(得分:2)

使用其他XML处理模块。例如,此脚本使用XML::XSH2XML::LibXML的包装:

#!/usr/bin/perl
use warnings;
use strict;

use XML::XSH2;

xsh << 'END';
    open input.xml ;
    for //*[xsh:matches(name(),'Pro')]/Identification/Address/Data
        set . 'hello' ;
    save :b ;
END

答案 2 :(得分:2)

XML :: Twig版本:

#!/usr/bin/perl 

use strict;
use warnings;

use XML::Twig;

XML::Twig->new( twig_roots => { 'Pro/Identification/Address/Data' => sub { $_->set_text( 'hello'); $_->flush; } },
                twig_print_outside_roots => 1,
              )
         ->parsefile( 'input.xml');

答案 3 :(得分:1)

另一种方式w / XML :: Rules

use strict;
use warnings;

use XML::Rules;

my @rules = (
  Data => sub { $_[1]{_content} =~ s/test/hello/; return $_[0] => $_[1] },
);
my $xr = XML::Rules->new(
  rules => \@rules,
  style => 'filter',
);

$xr->filterfile('input.xml');

答案 4 :(得分:0)

输出已将NoAttr设置为零。

这与你想要的不相反吗?

  

NoAttr =&gt; 1

     

与XMLout()一起使用时,生成的XML将不包含任何属性。   所有散列键/值都将表示为嵌套元素。

NoAttr会停止

<Phone>
    <Number>0000</Number>

变成

 <Phone name="Number">