简体   繁体   中英

In XML file, how to replace one attribute depending upon pattern match of some another attribute using perl?

I have XML file something like this

    <staticResources><staticMMOResource language="eng" variant="default" version="5" id="../../../shared_ip/pex/pex_shared/images/compatible_config_header-type_1_non_cust.svg">
</staticMMOResource>
        </staticXMLResource><staticXMLResource language="eng" variant="default" version="9" id="../../../shared_ip/pex/pci_express_1/topics/pci_express_extended_configuration_space.xml">
    </staticXMLResource><staticMMOResource language="eng" variant="default" version="3" id="../../../shared_ip/pex/pci_express_1/images/b2ac21.svg></staticMMOResource></staticResources>

I need to update the version attribute if the ID matches with particular set of IDs (I have stored all the required IDs in an array). Array has ID's like

pci_express_1/topics/pci_express_extended_configuration_space.xml
pci_express_1/images/b2ac21.svg

I need Output which looks like

<staticResources><staticMMOResource language="eng" variant="default" version="5" id="../../../shared_ip/pex/pex_shared/images/compatible_config_header-type_1_non_cust.svg">
    </staticMMOResource>
            </staticXMLResource><staticXMLResource language="eng" variant="default" version="11" id="../../../shared_ip/pex/pci_express_1/topics/pci_express_extended_configuration_space.xml">
        </staticXMLResource><staticMMOResource language="eng" variant="default" version="5" id="../../../shared_ip/pex/pci_express_1/images/b2ac21.svg></staticMMOResource></staticResources>

Please help!! I am new in Perl.

What you need to do this is something like this:

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

use XML::Twig;

my @ids = ( "../../../shared_ip/pex/pci_express_1/topics/pci_express_extended_configuration_space.xml" );

my $twig = XML::Twig -> parse ( \*DATA ); 
foreach my $id ( @ids ) { 
   foreach my $match ( $twig -> findnodes("staticXMLResource[\@id=\"$id\"]") ) {
       $match -> set_att('version', $match->att('version') + 1 );
   }
}
$twig -> print;

__DATA__
<XML>
<staticXMLResource language="eng" variant="default" version="9" id="../../../shared_ip/pex/pci_express_1/topics/pci_express_extended_configuration_space.xml">
</staticXMLResource>
</XML>
  • We load your XML. (I use DATA for illustration, because I have had to mock up some XML similar to yours. You probably shouldn't).
  • We iterate each of your IDs.
  • we look for elements that have an attribute matching that ID.
  • We retrieve the version, increment it, and then set that new value.

And then we print the XML.

You may find set_pretty_print to be useful for formatting.

Eg:

$twig -> set_pretty_print('indented_a');

Edit: Given you have included some array content - that doesn't precisely match your attribute, so you need to do it slightly differently:

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

use XML::Twig;

my @ids = qw ( pci_express_1/topics/pci_express_extended_configuration_space.xml 
        pci_express_1/images/b2ac21.svg );

#assemble a regex from the search elements. 
my $search = join ( "|", @ids ); 
   $search = qr/($search)/; 

#parse XML - you'll probably want "parsefile" or "parse" depending on your 
#XML source. 
my $twig = XML::Twig -> parse ( \*DATA ); 

#iterate the children of the root (staticResources) node 
# NB - this might not match your larger file. 
foreach my $resource ( $twig -> root -> children ) {
   #test if the 'id' attribute matches our regex. 
   #note - regex is unanchored, so substring matches work. 
   if ( $resource -> att('id') =~ m/$search/ ) { 
      #increment version id. 
      $resource -> set_att('version', $resource->att('version') + 1 ); 
   }
}
#set output format
$twig -> set_pretty_print('indented_a'); 
#print to stdout. 
#To print to a file, you may want print {$opened_fh} $twig -> sprint; 
$twig -> print; 

__DATA__
<staticResources>
<staticXMLResource language="eng" variant="default" version="9" id="../../../shared_ip/pex/pci_express_1/topics/pci_express_extended_configuration_space.xml">
    </staticXMLResource>
    <staticXMLResource language="eng" variant="default" version="9" id="../../../shared_ip/pex/pci_express_1/topics/pci_express_extended_configuration_space.xml">
</staticXMLResource>
<staticMMOResource language="eng" variant="default" version="3" id="../../../shared_ip/pex/pci_express_1/images/b2ac21.svg"></staticMMOResource>
</staticResources>

We build a search regex $search out of the patterns you have. Then we iterate your child nodes of your root (if your XML is bigger, then you might need to use get_xpath still).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM