Re: XML::LibXML::XPathContext namespace confusion
Grant McLean <[email protected]>
| Newsgroups | gmane.comp.lang.perl.xml |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 2009-09-09 at 18:09 -0400, Scott Stansbury wrote:
> I am confused with the namespace issues using XML::LibXML::XPathContext.
It *is* confusing. The key point is that the only thing that really
matters is the namespace URI. The prefix used in the document is not
relevant. Whether you choose to associate the URI with the same prefix
as was used in the document is your choice - XML::LibXML doesn't care
either way.
> my $xp = XML::LibXML::XPathContext->new($data_file);
Rather than passing the constructor a filename, you'll want to pass it a
document element - which means you'll have to parse the document first,
e.g.:
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file($data_file);
my $xc = XML::LibXML::XPathContext->new( $doc->documentElement() );
Now you need to register a namespace prefix for each namespace that you
want to use in a query, e.g.:
$xc->registerNs( def => 'http://scap.nist.gov/schema/feed/vulnerability/2.0' );
$xc->registerNs( vuln => 'http://scap.nist.gov/schema/vulnerability/0.4' );
$xc->registerNs( cvss => 'http://scap.nist.gov/schema/cvss-v2/0.2' );
Your example document included a default namespace declaration so every
element in the document without a namespace prefix is associated with
the default namespace URI (well that's an oversimplification but it will
do for now).
Now you'll use the XPathContext object to do the XPath searches:
for my $entry ($xc->findnodes("/def:nvd/def:entry[\@id = '$cve_id']")) {
Note I used the def: prefix to specify that I wanted to match elements
in the document default namespace.
The nodes that are returned are (confusingly) plain LibXML DOM nodes and
have no knowledge of namespaces so if you want to do a relative search
then you need to use the $xc object again and give it a context node:
my ($metrics) = $xc->findnodes('vuln:cvss/cvss:base_metrics', $entry)
or die "Failed to find metrics for entry $cve_id";
my $av = $xc->find('cvss:access-vector', $metrics);
That should be enough to get you going.
Cheers
Grant
_______________________________________________
Perl-XML mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs