http://www.perlmonks.org?node_id=225745

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

In the pod for XML::Filter::Dispatcher is says:
## Print the text of all <description> elements 'string( description )' => sub { print xvalue },
My problem is that to get this to work I have to write a full path to the description element, such as string( doc/head/description) in order to get the match. Also, it only matches the first tag.

Here is my full example, which is a slightly modified example from the pod:

use XML::Filter::Dispatcher qw ( :all ); use XML::SAX::Machines qw( Pipeline ); sub run { Pipeline( shift )->parse_string( <<XML_END ) } <stooges> <stooge name="Moe" hairstyle="bowl cut"> <attitude>Bully</attitude> </stooge> <stooge name="Shemp" hairstyle="mop"> <attitude>Klutz</attitude> <stooge name="Larry" hairstyle="bushy"> <attitude>Middleman</attitude> </stooge> </stooge> <stooge name="Curly" hairstyle="bald"> <attitude>Fool</attitude> <stooge name="Shemp" repeat="yes"> <stooge name="Joe" hairstyle="bald"> <stooge name="Curly Joe" hairstyle="bald" /> </stooge> </stooge> </stooge> </stooges> XML_END my $count; run( XML::Filter::Dispatcher->new( Rules => [ 'stooge' => sub { ++$count }, 'string( stooges/stooge/attitude )' => sub { print xvalue(),"\n" +; }, ], ) );
This prints the contents of only one <attitude> tag, and I want it to match all of them. When I substitute
'string( attitude )' => sub { print xvalue; },

as the pod seems to suggest, it no longer prints anything. Am I doing something wrong?

I already have something like this working in XML::Twig, so I can always go back to that.

Thanks!

It should work perfectly the first time! - toma

Replies are listed 'Best First'.
Re: XML::Filter::Dispatcher string rules problem
by barries (Initiate) on Jan 10, 2003 at 14:19 UTC
    Am I doing something wrong?

    Yup. Yer using poorly documented OSS software ;)

    The SYNOPSIS is badly outdated; I've updated it. The SYNOPSIS in the released version dates from before I made X::F::D more compliant with XPath. The updated SYNOPSIS looks like:

    use XML::Filter::Dispatcher qw( :all ); my $f = XML::Filter::Dispatcher->new( Rules => [ 'foo' => \&handle_foo_start_tag, '@bar' => \&handle_bar_attr, ## Send any <foo> elts and their contents to $handler 'snarf//self::node()' => $handler, ## Print the text of all <description> elements 'description' => [ 'string()' => sub { push @out, xvalue } ], ], Vars => { "id" => [ string => "12a" ], }, );

    The change that affects you is that string() now only looks at the first node in the nodeset as per XPath, so you need to get X::F::D to visit all the desired element nodes and then call string() nodes.

    There's now a t/synopsis.t that has the audacity to test the code from the SYNOPSIS. The next release will be heading CPANward as soon as I submit this.

    Thanks for the bug report.

    - Barrie

    P.S. I only found this question thanks to Matt Sergeant mentioning it. In general, while perlmonks is a nice resource, I recommend posting XML related questions to the perl-xml@listserv.ActiveState.com mailing list.

      There's now a t/synopsis.t that has the audacity to test the code from the SYNOPSIS. The next release will be heading CPANward as soon as I submit this.

      What a cool idea. Everyone should do this. Does it extract the code or did you just cut'n'paste? ++barries

                      - tye
      Thanks! This fixed my problem. Thanks also for the information on other sources of XML information.

      My evaluation of XML::Filter::Dispatcher was suggested by Matts when he commented on my blog at use perl. Like perl itself, much of the value of XML is the great group of people that are working on it and helping others.

      Thanks again!

      It should work perfectly the first time! - toma