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.
$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')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With