Anil
Anil

Reputation: 3992

Input XML data doen't match with the output XML format

Input 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>

Script:

I am trying to change the value of the tag and print the rest to a new output xml file

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>

I am able to change the value, but whem i am trying to write the data to the ouput the format has been changed.Can any one guide me to get the same input data with changed value as output.

Upvotes: 3

Views: 386

Answers (5)

AmbroseChapel
AmbroseChapel

Reputation: 12087

You've got NoAttr set to zero for the output.

Isn't that the opposite of what you want?

NoAttr => 1

When used with XMLout(), the generated XML will contain no attributes. All hash key/values will be represented as nested elements instead.

NoAttr would stop

<Phone>
    <Number>0000</Number>

turning into

 <Phone name="Number">

Upvotes: 0

runrig
runrig

Reputation: 6524

Yet another way 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');

Upvotes: 1

mirod
mirod

Reputation: 16161

An XML::Twig version:

#!/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');

Upvotes: 2

Memos Electron
Memos Electron

Reputation: 660

use XML::LibXML this way:

#!/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 is much faster and with the help of the XPath, the manipulation of the $xml_doc is much easier.

more infos you can find here

Upvotes: 4

choroba
choroba

Reputation: 241858

Use a different XML handling module. For example, this script uses XML::XSH2, a wrapper around XML::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

Upvotes: 2

Related Questions