in reply to XML::Twig Question

See XML::Twig 101 in the XML::Twig documentation. If you have a particular problem with your code post the code here and describe the problem.


Perl is Huffman encoded by design.

Replies are listed 'Best First'.
Re^2: XML::Twig Question
by ramya2005 (Scribe) on Aug 15, 2005 at 22:37 UTC
    Sir, I read the documentation for XML::Twig. But I have the following problem in achieving the required results.
    I have "books.xml" file with the following content.
    <Books> <Titles Mode="List"> <Title Name="Programming Perl"/> <Title Name="Advanced Perl Programming"/> <Title Name="Learning Perl on Win32 Systems"/> </Titles> </Books>
    I have the following code to access Title element with Name => 'Advanced Perl Programming' !
    my $filtername = 'Advanced Perl Programming'; my $books_tree= new XML::Twig(twig_roots => {Title[@Name= "$filtername +"] => 1}); $books_tree-> parsefile('books.xml'); $books_tree->set_att(Name => 'Advanced Perl');
    syntax error at Books.pl line 56, near "Title[" Global symbol "@Name" requires explicit package name at Books.pl line 56.
    Execution of Books.pl aborted due to compilation errors.
    Please help! Thanks
      #! /usr/bin/perl -w use strict; use warnings; use XML::Twig; my $filtername = 'Advanced Perl Programming'; my $books_tree= new XML::Twig(); $books_tree->parsefile('books.xml'); my @title = $books_tree->get_xpath(qq[//Title[\@Name="$filtername"]]); $_->set_att(Name => 'Advanced Perl') for @title; $books_tree->print();

      Step 1 - XPaths are strings, not perl data structures. Step 2 - I'm not too familiar with twig roots, so I load the entire data structure into memory, play with it, then print it back out. If you have a huge data structure that you want to stream, then we can start from here and move it back into twig roots that can parse/modify/output in a single statement, streaming and purging as you go.

      Hope that helps.

      Your example code is close, just not quite there yet.
      use strict; use XML::Twig; my $parser = new XML::Twig( twig_print_outside_roots => 1, twig_roots => { 'Title[@Name="Advanced Perl Programming"]' => sub { my ( $tree, $element ) = @_; $element->set_att( Name => 'Advanced Perl' ); $element->print; } } ); $parser->parse_file('books.xml');
      Notice a couple of things I did differently:
      - Put your twig_roots key in single quotes. Since you're using a '@' to select an element with an attribute, you don't want Perl to think you're trying to throw a variable name in there.
      - Rather than specifying your twig_roots value as a 1, use either a reference to a sub or an anonymous sub as I did above. This gives you a lot more flexibility to do what you want. Inside this sub, is where we want to change the "Name" attribute.
      - Specify twig_print_outside_roots so that it prints the rest of the document along with the twig_root you've specified

      That should do what you were attempting.

      --Brian
        Thank you! This code works.
        I tried to make use of the example code that you provided. It works! I am stuck when I try to enhance it to deal with two XML files. Please help!
        I have the following two XML files.

        books.xml
        <Books> <Titles Mode="List"> <Title Name="Programming Perl"/> <Title Name="Advanced Perl Programming"/> <Title Name="Learning Perl on Win32 Systems"/> </Titles> </Books>
        filter.xml
        <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' 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?

      What do you intend {Title[@Name= "$filtername"] => 1} to do? @Name is an array, but it does not appear in the code fragment except here. I suspect it is not declared anywhere, and doesn't seem to make sense here in any case.


      Perl is Huffman encoded by design.
        I am specifying 'attribute_condition' as it is specified in the XML::Twig document.
        tag[@att="val"]
        ?? Is my understanding about the usage is wrong?