in reply to Trees in XML

use strict; use XML::Rules; my $rules = XML::Rules->new( stripspaces => 7, rules => { _default => 'content', person => sub { # push the string we build to the array referenced by the +{person} # key in the paren tag's hash return '@person' => "$_[1]->{firstname} $_[1]->{lastname} +($_[1]->{age})" }, list => sub { # only interested in the person "attribute" # due to the previous rule it's an arary ref return $_[1]->{person}; # and this is what the $rules->parse() will return } } ); my $people = $rules->parse(\*DATA); use Data::Dumper; print Dumper($people); __DATA__ <?xml version='1.0' encoding='UTF-8'?> <list name="name list"> <person> <firstname>Paul</firstname> <lastname>Rutter</lastname> <age>24</age> </person> <person> <firstname>Ruth</firstname> <lastname>Brewster</lastname> <age>22</age> </person> <person> <firstname>Cas</firstname> <lastname>Creer</lastname> <age>23</age> </person> </list>

Replies are listed 'Best First'.
Re^2: Trees in XML
by Anonymous Monk on Jun 03, 2008 at 13:58 UTC
    thanks Jenda but unfotunately XML::Rules is not installed on my computer and seeing as it is managed I can't do it.

    In the mean time I have come up with this:

    #!/usr/bin/perl use strict; use warnings; use XML::Parser; use Data::Dumper; my $p = new XML::Parser( Style => 'Tree' ); my $inputfile = "testxml.xml"; my $tree = $p->parsefile($inputfile); print $tree->[1]->[4]->[4]->[2], "\n";
    which gives me 'Niall'

    As I said, need to stick with XML::Parser!

      As I said, need to stick with XML::Parser!

      Not exactly. You seem to have convinced yourself that 1- you need to only use XML::Parser, 2- the Tree style is the simplest way to get what you want. It seems to me that 1 is false lazyness, and 2 is just misguided.

      Learning how to use pure-perl modules, even on a machine where you don't have admin rights, would make it easier for you to write not only this piece of code, but also the next ones.

      Your problem seems really adapted to a stream processing, whether it's using XML::Parser or an other module. Your code would be much more resistant to changes in the XML structure in the future: in your example [1]->[4]->[4]->[2] is effectively the hardcoded (and some would say obfuscated) path to your target element. If you don't want to hardcode it, you will end up re-writing code that's already written in the likes of XML::Twig, XML::XPath, XML::Rules... Meanwhile with a stream processing you would just process the firstname element, and leave the rest as is, thus you would be able to apply your code even if the input XML changes, as long as it still includes a firstname element.

      That said, it's your code, you do what you want, just realize that you will get more help if you follow the general advice of using a better tool for the task.

      If you can upload your script you can upload XML::Rules as well. It's pure Perl, a single file and the only dependencies are strict, warnings, Carp and XML::Parser::Expat. The first three are core, I do believe if you have XML::Parser you have the last one.

      You can upload the Rules.pm into /some/path/you/have/access/to/lib/XML, add

      use lib '/some/path/you/have/access/to/lib';
      on top of your script and you are effectively done with the instalation.

      sorry, I mean:
      Paul