in reply to Re^2: XML::Twig question
in thread XML::Twig question

Here is what it would look like:

#!/usr/bin/perl use strict; use warnings; use XML::Twig; my( $ac_n_value, $ai_att_cond)= @ARGV; XML::Twig->new( twig_handlers => { qq{AC[\@n="$ac_n_value"]//AI[$ai_at +t_cond]} => \&print_ai_data }) ->parsefile( "test_thandi.xml"); sub print_ai_data { my( $t, $ai)= @_; print "DESC: ", $ai->first_child( 'Desc')->sprint, "\n", "ID : ", $ai->first_child( 'ID') ->sprint, "\n" ; }

You call this with the value you want for the n attribute of the AC element, and the condition for the AI element:

perl test_thandi CCC '@n=AAA' perl test_thandi CCC '@n="AAA" or @set="y"'

A couple of comments on the code: Perl and XPath strings don't really mix very well: you can use alternate quotes (qq{}) to avoid the collision of perl interpolating quotes and of XPath attribute quotes (or you can use ' instead of " in the XPath expression), but you need to backslash the @ used for attribute conditions in XPath, so it is not interpolated as an array by Perl. An alternate method is to use sprintf to build the XPath expression.

This code loads the entire document in memory, which you may or may not want. There are techniques to avoid this described in the XML::Twig Tutorial.

Also, you need the development version of XML::Twig to be able to run this, you can get it from xmltwig.com.

Replies are listed 'Best First'.
Re^4: XML::Twig question
by Bizza (Initiate) on Dec 19, 2006 at 21:50 UTC
    Below are the queries that I need to formulate based on the xml at the bottom. I'll also have to add a new node e.g starting from the <ID>..</ID> tks before hand thandi
    1. List All ACs in xml document result should be: AC desc AC=CCC, CL=CCC AC desc AC=AAA, CL=CCC # these are the <Desc> element just bel +ow start tag <AC> also need to be able to update the text if requeste +d. 2. List all AIs in a given AC, eg AC=CCC result should be: AI desc AI=BBB, AC=CCC AI desc AI=XXX, AC=CCC 3. List all <ID> nodes in a given <AI n="XXX"> result should be: a. ID desc ID=XXX, AI=BBB, AC=CCC What XXX ID ID_XXX b. ID desc ID=ZZZ, AI=BBB, AC=CCC What ZZZ ID ID_ZZZ The based on the user selection, I need to update the requested text w +ithin an element or add a whole new node. <World n="earth" > <Space n="XXX"> <CL n="XXX"> <Desc>Class description</Desc> <Other/> <AC n="AAA" set="n"> <Desc>AC desc AC=AAA, CL=CCC</Desc> <AI n="AAA" set="n"> <Desc>AI descr AI=AAA, AC=AAA</Desc> <ID n="AAA" set="y"> <Desc>ID desc ID=AAA, AI=AAA, AC=AAA</Desc> <What>What ID=AAA AI=AAA, AC=AAA</What> <AR>ID_aaa</AR> </ID> <ID n="BBB" set="y"> <Desc>ID desc ID=BBB, AI=AAA, AC=AAA</Desc> <What>What ID=BBB AI=AAA, AC=AAA</What> <AR>ID_bbb</AR> </ID> </AI> <AI n="BBB" set="y"> <Desc>AI desc, AI=BBB, AC=AAA</Desc> <ID n="AAA" set="y"> <Desc>ID desc ID=AAA, AI=BBB, AC=AAA</Desc> <What>What AAA ID=BBB, AI=BBB, AC=AAA </What> <AR>ID_bbb</AR> </ID> </AI> </AC> <AC n="CCC" set="y"> <Desc>AC desc ACC=CCC, CL=CCC</Desc> <AI n="AAA" set="n"> <Desc>AI desc AI=BBB, AC=CCC</Desc> <ID n="AAA" set="y"> <Desc>ID desc ID=AAA, AI=AAA, AC=CCCC</Desc> <What>What AAA ID=AAA, AI=AAA, AC=CCC </What> <AR>ID_aaa</AR> </ID> </AI> <AI n="XXX" set="n"> <Desc>AI desc AI=XXX, AC=CCC</Desc> <ID n="XXX" set="y"> <Desc>ID desc ID=XXX, AI=BBB, AC=CCC</Desc> <What>What XXX ID </What> <AR>ID_XXX</AR> </ID> <ID n="ZZZ" set="y"> <Desc>ID desc ID=ZZZ, AI=BBB, AC=CCC</Desc> <What>What ZZZ ID </What> <AR>ID_ZZZ</AR> </ID> </AI> </AC> </CL> </Space> </World>

      Are you the same person that asked the original question? You don't have the same user name.

      What did you try? Did you use my previous answer as a base and try changing it to do what you want? Is there anything I should add to the tutorial or the docs of the module to make them clearer? Thanks.

        Yea, same guy. Had problems at home with other user then use bizza user.

        Belows what I've done. Firstly, I found out that the inner elements <ID> are processed before the outer ones <AC>. With the twig_handlers, all of them are being processed eventhough, for e.g you only want a listing of <AC>'s. I think I'll have if stmts to check what the users requesting.

        The tutorial is too lightweight, xml examples doesn't really deal or include examples attribute checking/extraction. Actually, the xml file used(nba.xml)to simple, hence the simple examples.

        Also some XML::XPath usage would be great. This doesn't come thru' even in the developer version document. I think the tutorial should include a comprehensive xml file with attributes. I should show how extract and/or update specific elements (attribs and tags), how to find specific nodes, delete, modify and update em, traverse the doc. Because of the myriad of methods, classes and/or options available to perform a function - in maybe both "normal twiggy way" and xpath way.

        There's a lotta things to say, however that's one for another topic. The way it is, to pick XML::Twig is really difficult

        Bizza(thandi)

        HERE're my attempts at getting to know and understand: #!/usr/bin/perl use strict; use warnings; use XML::Twig; # perl test_thandi CCC '@n=AAA' # perl test_thandi CCC '@n="AAA" or @set="y"' my( $ac_n_value, $ai_att_cond)= @ARGV; XML::Twig->new( TwigHandlers => { # qq{AC[\@n="$ac_n_value"]/AI[$ai_att_cond]} => \&print_ai_data }, # qq{AC[\@n="$ac_n_value"]/AI[$ai_att_cond]/ID[\@n=$id_att_cond]} => + \&print_id_data }, # ID => \&id_print , #list all IDs desc <desc> </desc> # AI => \&ai_print , qq{AC} => \&ac_print, #list all ACs <desc> </desc> qq{AC/AI} => \&ai_print, #list all AIs <desc> </desc> }, pretty_print => 'indented', # keep_atts_order => 1, # do_not_chain_handlers => 1 ) ->parsefile( "custs.xml"); sub ac_print { my( $t, $ac)= @_; my $Desc = $ac->first_child('Desc')->text; print "AC DESC: $Desc\n"; print "=======================================\n"; } sub ai_print { my( $t, $ai)= @_; my $Desc = $ai->first_child('Desc')->text; print "AI DESC: $Desc\n"; print "----------------------------------\n"; } sub id_print { my( $t, $id)= @_; my $Desc = $id->first_child('Desc')->text; my $What = $id->first_child('What')->text; my $AR = $id->first_child('AR')->text; print "--> DESC: $Desc\n"; print "What: $What\n"; print "AR: $AR\n"; }