in reply to XML parsing

I haven't had to do anything with XML that I couldn't get done with XML::Twig. May $DEITY bless mirod.

Replies are listed 'Best First'.
Re^2: XML parsing
by mading0 (Initiate) on Oct 03, 2014 at 17:26 UTC
    Perhaps you can help me with Twig, then. What I want to do is search within a parent node for a specific text content of an element. If it doesnt match the string, then delete the entire parent node. Here's an example:
    <book> <book1>Book1</book1> <title>Title of Book 1</title> <genre>Fantasy</genre> </book>
    What I'd like to do in this case is search within each <book> and see if the title matches "Title of Book 1". If it doesn't, I want that entire <book> deleted. Does this make sense?

      See the section "Building an XML filter" of XML::Twig. Here's a quick implementation:

      use XML::Twig; open my $ofh, '>', $output_filename or die $!; XML::Twig->new( twig_print_outside_roots => $ofh, keep_spaces => 1, twig_roots => { book => sub { my ($twig, $book) = @_; if ($book->first_child_text('title') eq 'Title of Book 1') { $book->flush($ofh); } else { $book->purge; } return 1; } }, )->parsefile($input_filename); close $ofh;
      I would say that your example is probably over simplistic, so I've expanded on and cleaned it up slightly:
      <library> <book> <book1>Book1</book1> <title>Title of Book 1</title> <genre>Fantasy</genre> </book> <book> <book2>Book2</book2> <title>Not the Title of Book 1</title> <genre>Fantasy</genre> </book> </library>

      Now that we have something that's a little bit easier to show off some stuff, here's an example that does exactly what you ask.
      use strict; use warnings; use XML::Twig; use Data::Dumper; my $DATA = ' <library> <book> <book1>Book1</book1> <title>Title of Book 1</title> <genre>Fantasy</genre> </book> <book> <book2>Book2</book2> <title>Not the Title of Book 1</title> <genre>Fantasy</genre> </book> </library> '; my $source_twig = XML::Twig->new('pretty_print' => 'indented'); $source_twig->safe_parse($DATA); foreach my $book ($source_twig->root->children('book')) { if ($book->first_child('title')->text() ne 'Title of Book 1') { $book->cut() } } $source_twig->print();

      And it's output:
      <library> <book> <book1>Book1</book1> <title>Title of Book 1</title> <genre>Fantasy</genre> </book> </library>