6

I have the following XML as an example:

<root xmlns="http://www.plmxml.org/Schemas/PLMXMLSchema" >
    <parentNode status="Good">
        <A>
            <B>
                <C id="123" >C Node Value Here</C>
            </B>
        </A>
    </parentNode>
</root>

There are multiple parentNode nodes in my XML file (only one shown here), so I am cycling through parentNode's. Once I have one, I want to obtain attribute values 3 more levels down in the XML. My XML uses a name space and I have registed the name space in my Perl script as "plm". I can obtain the parentNode attribute value just fine using name space in my path. But when I try to navigate down to node "C" and pickup attribute "id", I am getting the following error:

XPath error : Undefined namespace prefix error : xmlXPathCompiledEval: evaluation failed

I am using the following Perl script.

use XML::LibXML;
use XML::LibXML::XPathContext;

my $filename = "namespaceissue.xml";

my $parser = XML::LibXML->new();
my $doc    = $parser->parse_file($filename);
my $xc = XML::LibXML::XPathContext->new( $doc->documentElement()  );
$xc->registerNs('plm', 'http://www.plmxml.org/Schemas/PLMXMLSchema'); 

foreach my $node ($xc->findnodes('/plm:root/plm:parentNode')) {
    my $status  = $node->findvalue('./@status');
    print "Status = $status\n";

    my $val = $node->findvalue('./plm:A/plm:B/plm:C/@title');
    print "Value = $val\n";

}

If I use no namespace on the sub-nodes ./A/B/C, the script continues with no error, but no value is assigned to $val. If I add the plm: prefix I get the namespace error. Does anybody know what I am doing wrong here? Do I have to use findnodes to first find the subnodes and then extract the value with findvalue? I tried that as well and did not have any luck.

1 Answer 1

4
$node->findvalue('./plm:A/plm:B/plm:C/@title')

should be

$xc->findvalue('./plm:A/plm:B/plm:C/@id', $node)

Tips:

  • Those leading ./ are useless.

    $node->findvalue('./@status')
    
    $xc->findvalue('./plm:A/plm:B/plm:C/@id', $node)
    

    are the same as

    $node->findvalue('@status')
    
    $xc->findvalue('plm:A/plm:B/plm:C/@id', $node)
    
  • You can use getAttribute to get an element's attribute, so

    $node->findvalue('@status')
    

    can also be accomplished more efficiently using

    $node->getAttribute('status')
    
Sign up to request clarification or add additional context in comments.

1 Comment

Thank You. I actually had a typo in what I published, so the following actually fixed my issue. I will have to read up some more on findvalue now. my $val = $xc->findvalue('./plm:A/plm:B/plm:C/@id', $node);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.