1

This may be very novice of me, but I am a novice at Perl LibXML (and XPath for that matter). I have this XML doc:

<Tims
    xsi:schemaLocation="http://my.location.com/namespace http://my.location.com/xsd/Tims.xsd"
    xmlns="http://my.location.com/namespace"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink">
        <Error>Too many entities for operation.  Acceptable limit is 5,000 and 8,609 were passed in.</Error>
        <Timestamp>2012-07-27T12:06:24-04:00</Timestamp>
        <ExecutionTime>41.718</ExecutionTime>
</Tims>

All I want to do is get the value of <Error>. Thats all. I've tried plenty of approaches, most recently this one. I've read the docs through and through. This is what I currently have in my code:

#!/usr/bin/perl -w

my $xmlString = <<XML;
<?xml version="1.0" encoding="ISO-8859-1"?>
<Tims
    xsi:schemaLocation="http://my.location.com/namespace http://my.location.com/xsd/Tims.xsd"
    xmlns="http://my.location.com/namespace"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink">
    <Error>Too many entities for operation.  Acceptable limit is 5,000 and 8,609 were passed in.</Error>
    <Timestamp>2012-07-27T12:06:24-04:00</Timestamp>
    <ExecutionTime>41.718</ExecutionTime>
</Tims>
XML

use XML::LibXML;

my $parser = XML::LibXML->new();
my $doc = $parser->parse_string($xmlString);
my $root = $doc->documentElement();
my $xpc = XML::LibXML::XPathContext->new($root);

$xpc->registerNs("x", "http://my.location.com/namespace");

foreach my $node ($xpc->findnodes('x:Tims/x:Error')) {
        print $node->toString();
}

Any advice, links, anything is appreciated. Thanks.

Community
  • 1
  • 1
Honus Wagner
  • 2,830
  • 13
  • 44
  • 61

2 Answers2

2

Just add a / at the beginning of the XPath (i.e. into findnodes).

choroba
  • 231,213
  • 25
  • 204
  • 289
0

Your code isn't working because you use the document element <Tims> as the context node when you create the XPath context $xpc. The <Error> element is an immediate child of this, so all you need to write is

$xpc->findnodes('x:Error')

or an alternative is to use an absolute XPath which specifies the path from the document root

$xpc->findnodes('/x:Tims/x:Error')

That way it doesn't matter what the context node of $xpc is.

But the proper way is to forget about fetching the element node altogether and use the document root as the context node. You can also use findvalue instead of findnodes to get the text of the error message without the enclosing tags:

my $parser = XML::LibXML->new;
my $doc = $parser->parse_string($xmlString);

my $xpc = XML::LibXML::XPathContext->new($doc);
$xpc->registerNs('x', 'http://my.location.com/namespace');

my $error= $xpc->findvalue('x:Tims/x:Error');
print $error, "\n";

output

Too many entities for operation.  Acceptable limit is 5,000 and 8,609 were passed in.
Borodin
  • 126,100
  • 9
  • 70
  • 144