Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

nodelists and nodesets

by nonnonymousnonk (Novice)
on Nov 22, 2007 at 15:41 UTC ( #652397=perlquestion: print w/ replies, xml ) Need Help??
nonnonymousnonk has asked for the wisdom of the Perl Monks concerning the following question:

Hi monks,

XML::xpath is making my brain ache, perhaps someone can enlighten me.

It's taken a while but I think I'm starting to understand the differences between a nodeset and a node list. I'm sure I've not got it fully because my code so far is not that nice.

What I'm doing is getting a nodeset using find(), for example:

my $xp = XML::XPath->new(filename => $file); $plantdata->{nodeset} = $xp->find('//loop_device[@loop_number="1"]');

I then run though the nodes like this

foreach my $device ($plantdata->{nodeset}->get_nodelist()) { $devicename = find('devicename')->string_value; $devicetype = find('devicetype')->string_value; do more stuff }

Most of the time I'm just getting attributes as in the above code and chucking them out to an Excel spreadsheet but for a few values of $devicetype I need to dig deeper into the XML and this is where I'm stuck.

What I've done is go back to the beginning like this:

if ($devicetype eq "complex") { $seachstring = sprintf "//loop_device[@devicename=\"%s\"]/subdevice" +, $devicename; $subdevice = $xp->find($searchstring); }

I'm doing this because $device is a node from a node list not from a nodeset so I can't do this:

$subdevice = $device->find('/subdevice');

If I go into the debugger and look at $plantdata->{nodeset} and $device both seem to contain a hell of a lot more than just the node I want. Is there a way to turn a $device node back into a nodeset so that I can dig deeper into it rather than going back to $xp and starting again?

Thanks
Nonk

Comment on nodelists and nodesets
Select or Download Code
Re: nodelists and nodesets
by Cody Pendant (Prior) on Nov 22, 2007 at 23:48 UTC
    Three quick things:
    • A "nodelist" is not an XSL concept
    • XSL has nodesets, and the module has a get_nodelist method just to help you go through your nodes one by one
    • without actually seeing your XML, or knowing what you're trying to do, it's pretty much impossible to help you


    Nobody says perl looks like line-noise any more
    kids today don't know what line-noise IS ...
      I can't find a single place in the OP were 'XSL' or 'stylesheet' or 'translate' are mentioned.

      Has the OP been silently updated since you replied?

      -David

Re: nodelists and nodesets
by erroneousBollock (Curate) on Nov 23, 2007 at 03:33 UTC
    What I'm doing is getting a nodeset using find(), for example:

    my $xp = XML::XPath->new(filename => $file); $plantdata->{nodeset} = $xp->find('//loop_device[@loop_number="1"]');
    Which returns an XML::XPath::NodeSet.

    Calling $plantdata->{nodeset}->get_nodelist() will return a list of XML::Node (and/or descendant) objects.

    What I've done is go back to the beginning like this:

    if ($devicetype eq "complex") { $seachstring = sprintf "//loop_device[@devicename=\"%s\"]/subdevice" +, $devicename; $subdevice = $xp->find($searchstring); }
    That's unnecessary, using $device (which in your case is an XML::XPath::Node object returned from $nodeset->get_nodelist())as the context is fine.

    I'm doing this because $device is a node from a node list not from a nodeset so I can't do this:

    $subdevice = $device->find('/subdevice');
    Yes, you can :-). The synopsis in the XML::XPath::NodeSet documentation shows that usage pattern.

    I don't know the structure of your XML (you've not provided a sample), but that is exactly how this sort of this is usually done.

    If I go into the debugger and look at $plantdata->{nodeset} and $device both seem to contain a hell of a lot more than just the node I want. Is there a way to turn a $device node back into a nodeset so that I can dig deeper into it rather than going back to $xp and starting again?
    Now, why would you use a debugger to look in the XML::XPath::Node object? ;)

    Actually, every node object returned from the initial XPath context has a references back to the main XPath context's XML DOM. That's likely what you're seeing in the debugger.

    XML::XPath::Node objects must have the full context, otherwise you couldn't perform XPath queries like

      $node->find('/foo/../../../bar[2]');

    because the context wouldn't be there to traverse!

    The moral of the story is to use DOM methods to traverse the XML DOM, not a debugger.

    -David

      Thanks David,

      That's unnecessary, using $device (.....) as the context is fine.

      'Context' is the magic word that made the penny drop. This:

      $subdevice = $device->find('/subdevice', $device);
      Does just what I need.

      I was only looking at stuff in the debugger to try to understand the difference between nodesets and node lists. It wasn't helpful as both are far too large to read.
      All I could really gleen was whether my code was giving vaguely sensible results.

      Thanks a mill
      Nonk

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://652397]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2014-12-21 01:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (100 votes), past polls