Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Problem in parsing XML file using XMl::Twig

by ramya2005 (Scribe)
on Aug 16, 2005 at 21:35 UTC ( #484255=perlquestion: print w/replies, xml ) Need Help??

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

I have the following two XML files.

<Books> <Titles Mode="List"> <Title Name="Programming Perl"/> <Title Name="Advanced Perl Programming"/> <Title Name="Learning Perl on Win32 Systems"/> </Titles> </Books>
<Filters> <Titles> <Title Name="Programming Perl"/> <Title Name="Advanced Perl Programming"/> <Title Name="Learning Perl on Win32 Systems"/> </Titles> </Filters>
I am trying to do the following using the code below.
1. Change the 'Title Name' in 'books.xml' by appending the existing 'Title Name' with some random number.
2. Change the corresponding 'Title Name' in 'filter.xml'
use XML::Twig; # Learning XML testing functions ReadBooksInfo('books.xml','filter.xml'); sub ReadBooksInfo{ my $books_name = shift; my $filter_name = shift; my $filter_tree; my $books_tree= new XML::Twig( TwigHandlers => { Title => sub { my( $titletwig, $title_ele ) = @_; + my $titlename = $title_ele->att('Name'); my $unique_titlename = CreateUniqueFilterName($filterna +me); print "\nGenerated unique title name: ", $unique_title +name; print "\n"; $title_ele->set_att( Name => "$unique_titlename "); $filter_tree= new XML::Twig( TwigHandlers => { qq[Title[\@Name="$titlename"]] => sub { my ( $tree, $element ) = @_; $element->set_att( Name => "$unique_titlena +me" ); $element->print; } } ); $filter_tree->parsefile($filter_name); } } ); $filter_tree->parsefile( $books_name ); $filter_tree->print; $books_tree->print; } # Create unique filter names # =========================== sub CreateUniqueFilterName { my $user_filter_name = shift; my $lower=1000; my $upper=2000000; my $random = int(rand( $upper - $lower + 1 ) ) + $lower; my $unique_filter_name = $user_filter_name . "_". "$$". "_". "$^T" +. "_" .$random; }
Now the problem is I am able to correctly parse the items. But at at the end when I print the 'books_tree - twig' only the Title name 'Learning Perl on Win32 Systems' reflects the changes. Everything else is same as the original books.xml file.

Please tell me how to fix this?

Replies are listed 'Best First'.
Re: Problem in parsing XML file using XMl::Twig
by mirod (Canon) on Aug 16, 2005 at 22:55 UTC

    Actually what should happen (I did not run the code) is that your program prints the modified element in books.xml for each title (from the element->print in the loop, then prints the entire books.xml resulting from the last loop, where indeed only 'Learning Perl on Win32 Systems' has been updated.

    What are you trying to do exactly? The example seems really contrived.

    In any case, your existing code processes books.xml and awfull lots of time (once per title)! If you really wanted to do this you should parse the first file, changing the titles and storing a hash old_title => new title (if memory is a problem you can use twig_roots / purge during the parse and tie the hash to a DBM file), then parse the second file, and replace each title found in the hash by the value (once again using twig_roots / purge if memory is tight).

    Does this help?

      Thanks that tip helps!
Re: Problem in parsing XML file using XMl::Twig
by Roger (Parson) on Aug 16, 2005 at 21:48 UTC
    What do you think $$titlename will interpolate as? It will give you the pid of the process + the text 'titlename'.

      Actually it looks like $$titlename will dereference the scalar instead:
      perl -wle 'use strict; my $bar = 3; my $foo = \$bar; print "$$foo"' # outputs: 3
      But OP probably doesn't want to use $titlename as a scalar ref .. so the line qq[Title[\@Name="$$titlename"]] => should probably be:
      qq[Title[\@Name="$$titlename"]] =>

      to OP: use strict; and use warnings; would have caught this saying something like Can't use string ("MyTitleString") as a SCALAR ref while "strict refs" in use at line 1234.
        I am sorry! That was a typo created when I copied the code and pasted it in Perl Monks editor. It is one $. And still the problem exists...
        But I realized that I am doing 'new' in a loop and that's why I am loosing the data.
        Can someone suggest me how to correct it?
        Is there a way to create new Xml::Twig and set the handler later?

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2023-02-07 01:38 GMT
Find Nodes?
    Voting Booth?
    I prefer not to run the latest version of Perl because:

    Results (38 votes). Check out past polls.