0

Looking to return the full xpath from a general xpath that may grab multiple results.

The search string would be something general like this: /myXmlPath/@myValue

The contained xml nodes might look something like this:

<myXmlPath someAttribute="false" myValue="">
<myXmlPath someAttribute="true" myValue="">

Perl code something like this:

use XML::LibXML;
use XML::XPath::XMLParser;

my $filepath =  "c:\\temp\\myfile.xml";
my $parser = XML::LibXML->new();
$parser->keep_blanks(0);
my $doc    = $parser->parse_file($filepath);

@myWarn = ('/myXmlPath/@myValue');
 foreach(@myWarn) {
   my $nodeset = $doc->findnodes($_);
        foreach my $node ($nodeset->get_nodelist) {

        my $value = $node->to_literal;
            print $_,"\n";   
            print $value," - value \n";     
            print $node," - node \n";      

                }
   }

I'd like to be able to evaluate the returned full path values from the xml. This code works fine when I'm using it to lookup general things in an xpath, but would be more ideal if I could get at other data from the nodeset result.

  • I don't quite understand what you want. Could you include the desired output? But first, could you fix your example so it's valid XML? (What you provided has multiple root nodes and unclosed elements.) – ikegami Aug 27 '15 at 17:35

1 Answers1

1

Like ikegami said, I'm not sure exactly what you're after so I've kind of produced a shotgun approach for everything I could interpret your question.

use strict;
use warnings;

use XML::LibXML;

use v5.14;

my $doc = XML::LibXML->load_xml(IO => *DATA);

say "Get the full path to the node";
foreach my $node ($doc->findnodes('//myXmlPath/@myValue')) {
    say "\t".$node->nodePath();
}

say "Get the parent node of the attribute by searching";
foreach my $node ($doc->findnodes('//myXmlPath[./@myValue="banana"]')) {
    say "\t".$node->nodePath();
    my ($someAttribute, $myValue) = map { $node->findvalue("./$_") } qw (@someAttribute @myValue);
    say "\t\tsomeAttribute: $someAttribute";
    say "\t\tmyValue: $myValue";
}

say "Get the parent node programatically";
foreach my $attribute ($doc->findnodes('//myXmlPath/@myValue')) {
    my $element = $attribute->parentNode;
    say "\t".$element->nodePath();
}


__DATA__
<document>
<a>
  <b>
    <myXmlPath someAttribute="false" myValue="apple" />
  </b>
  <myXmlPath someAttribute="false" myValue="banana" />
</a>
</document>

Which would produce:

Get the full path to the node
    /document/a/b/myXmlPath/@myValue
    /document/a/myXmlPath/@myValue
Get the parent node of the attribute by searching
    /document/a/myXmlPath
        someAttribute: false
        myValue: banana
Get the parent node programatically
    /document/a/b/myXmlPath
    /document/a/myXmlPath
Tim Tom
  • 779
  • 3
  • 6
  • Apologies for the question not being clear enough, but you got it more or less.I'm really looking for nodePath() of the found general element. /xmlLevel1/xmlLevel2/xmlLevel3/xmlLevel4[@name='something']/@enableSomething /xmlLevel1/xmlLevel2[1]/xmlLevel3/xmlLevel4[3] /xmlLevel1/xmlLevel2[2]/xmlLevel3/xmlLevel4[3] – Bruce Allen Aug 30 '15 at 13:07