Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

xml to xml converter

by szpt9m (Novice)
on Nov 09, 2021 at 14:14 UTC ( #11138619=perlquestion: print w/replies, xml ) Need Help??

szpt9m has asked for the wisdom of the Perl Monks concerning the following question:

Hello, I need a way to search and find some tags and values in my input xml and if that exist, i want to create a new xml file based on that. For example my input file looks something as below
<?xml version="1.0" encoding="UTF-8"?> <TestCode version="10.0"> <TestCategory name="SmokeTest"> <Test name="CheckType_123" type="String"> <Test_description>No description available for this Test < +/Test_description> <context name="Testing"> <value>ABC</value> <value>XYZ</value> </context> </Test> <Test name="CheckType_PQR" type="String"> <Test_description>No description available for this Test</ +Test_description> <context name="SmokeTest"> <value>ABC</value> </context> </Test> <Test name="ValueAdded_123" type="String"> <Test_description>No description available for this Test</ +Test_description> <context name="Testing"> <value>ABC</value> <value>XYZ</value> </context> </Test> </TestCategory> </TestCode>
From the above input xml file, I need to check if i have tag <Test name=CheckType_* and if yes, i need to check if i have context/vlaue = XYZ. If exist i need to take the whole <Test ...> </Test> tag and put it in a new xml file. So from the above xml, the output what i need is:
<?xml version="1.0" encoding="UTF-8"?> <TestCode version="10.0"> <TestCategory name="SmokeTest"> <Test name="CheckType_123" type="String"> <Test_description>No description available for this Test</ +Test_description> <context name="Testing"> <value>ABC</value> <value>XYZ</value> </context> </Test> </TestCategory> </TestCode>
because from my input xml, the second Test tag has no value XYZ and 3rd Test tag has no name starting with CheckType_*. Can you help me with this?

Replies are listed 'Best First'.
Re: xml to xml converter
by haukex (Bishop) on Nov 09, 2021 at 14:39 UTC

    Although my go-to XML module is XML::LibXML, XML::Twig is useful for filtering XML files. The following produces your expected output for the given input:

    use warnings; use strict; use XML::Twig; use XML::XPath; # for findnodes my $filename = 'foo.xml'; XML::Twig->new( twig_print_outside_roots => 1, keep_spaces => 1, twig_roots => { '/TestCode/TestCategory/Test' => sub { my ($t, $elt) = @_; if ( $elt->{att}{name} =~ /^CheckType_/ ) { my @values = $elt->findnodes('./context/value'); # could theoretically also use XPath for the following if ( grep { $_->text =~ /XYZ/ } @values ) { $t->flush } else { $t->purge } } else { $t->purge } }, }, )->parsefile($filename);
      Thank you for quick response but i get an error Can't locate XML/Twig.pm in @INC when running this. How can i install in module in Windows?
        Thank you for quick response but i get an error Can't locate XML/Twig.pm in @INC when running this. How can i install in module in Windows?

        The same way you would install any other module. In Strawberry Perl, cpanm XML::Twig XML::XPath works for me.

Re: xml to xml converter
by choroba (Archbishop) on Nov 09, 2021 at 16:30 UTC
    This is how you can do it in XML::XSH2, a wrapper around XML::LibXML. You can experiment with the code in its xsh shell interactively.
    my $out := create "TestCode" ; set $out/TestCode/@version "10.0" ; set $out/TestCode/TestCategory/@name "SmokeTest" ; open file.xml ; cp //Test[starts-with(@name, "CheckType_")][context/value = "XYZ"] into $out/TestCode/TestCategory ; save :f output.xml $out ;

    Or maybe, more simply, remove any Test that doesn't match the criteria:

    open 1.xml ; delete ( //Test[not(starts-with(@name, "CheckType_"))] | //Test[starts-with(@name, "CheckType_")][not(context/value = +"XYZ")] ) ; save :f 1.out ;

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
Re: xml to xml converter
by perlfan (Vicar) on Nov 10, 2021 at 10:56 UTC
    Idk if one of the utlilties provided by WC3's HTML/XML utilities, which reminds me Perl has no interface to this. When this comes up, I always want to create a module that embeds these tools (like DBD::SQLite embeds sqlite3) and provide a Perl interface to them...maybe one day. :)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11138619]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2022-06-30 09:39 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My most frequent journeys are powered by:









    Results (97 votes). Check out past polls.

    Notices?