XML::Twig

TL;DR

A few notes about the XML::Twig that is useful to me (these days).

XML::Twig is amazing but the documentation can be a bit… daunting.

Fact is that it does a lot of things. It’s handy and it’s also amazing at providing means to deal with huge XML documents in all possibly flexible ways.

Anyway, this is not my use case. I need something that can grok XML and give me a reasonable way to deal with it. Another alternative I’ll look into is Mojo::DOM, but for today… XML::Twig.

This is my SYNOPSIS, which is a working copy-and-paste example of a subset of the whole API:

#!/usr/bin/env perl
use v5.24;
use warnings;

use XML::Twig;

my $twig = XML::Twig->new(pretty_print => 'indented');

#$twig->parsefile($filename);
#$twig->parse($xml_string);
$twig->parse(\*DATA);

say $twig->toString;

my ($collection) = $twig->findnodes('/result/collection');
say $collection->toString;
if ($collection->has_atts) { # yes it has
   say "\ncollection has attributes:";
   my @names = sort { $a cmp $b } $collection->att_names;
   for my $name (@names) {
      my $value = $collection->att($name);
      say "'$name' -> '$value'";
   }
   my $attributes_hashref = $collection->atts;
   say for keys $attributes_hashref->%*;
}
say '';

my @items = $twig->findnodes('//item');
my $item = pop @items;
say $item->tag, ' has ', $item->children_count, ' children';

say ' (it contains no attribute)' unless $item->has_atts;

for my $child ($item->children) {
   say ' - ', $child->tag;
   if ($child->has_children) {
      say '     has children (', $child->children_count, ')';
      my $grandchild = $child->first_child;
      say '          that is text <', $grandchild->text, '>'
         if $grandchild->is_text;
   }
   elsif ($child->is_empty) {
      say '     is empty';
   }
}

__END__
<?xml version = "1.0"?>
<result>
   <collection what="ever" you="do">
      <item>
         <foo>This is foo</foo>
         <bar/>
      </item>
      <item>
         <foo>This is foo, too</foo>
         <bar>This is arguably bar</bar>
         <baz/>
      </item>
   </collection>
</result>

So… let’s run it:

$ perl xmltwig.pl 
<?xml version="1.0"?>
<result>
  <collection what="ever" you="do">
    <item>
      <foo>This is foo</foo>
      <bar/>
    </item>
    <item>
      <foo>This is foo, too</foo>
      <bar>This is arguably bar</bar>
      <baz/>
    </item>
  </collection>
</result>


  <collection what="ever" you="do">
    <item>
      <foo>This is foo</foo>
      <bar/>
    </item>
    <item>
      <foo>This is foo, too</foo>
      <bar>This is arguably bar</bar>
      <baz/>
    </item>
  </collection>

collection has attributes:
'what' -> 'ever'
'you' -> 'do'
you
what

item has 3 children
 (it contains no attribute)
 - foo
     has children (1)
          that is text <This is foo, too>
 - bar
     has children (1)
          that is text <This is arguably bar>
 - baz
     is empty

I hope it can be useful… stay safe anyway!


Comments? Octodon, , GitHub, Reddit, or drop me a line!