tags:

views:

104

answers:

1

This script works with and without XPathContext. Why should I use it with XPathContext?

#!/usr/bin/env perl
use warnings; use strict;
use XML::LibXML;
use 5.012;

my $parser = XML::LibXML->new;

my $doc = $parser->parse_string(<<EOT);
<?xml version="1.0"?>
<xml>
    Text im Dokument
    <element id="myID" name="myname" style="old" />
    <object objid="001" objname="Object1" />
    <element id="002" name="myname" />
</xml>
EOT 
#/

# without XPathContext
my $nodes = $doc->findnodes( '/xml/element[@id=002]' );

# with XPathContext
#my $root = $doc->documentElement;
#my $xc = XML::LibXML::XPathContext->new( $root );
#my $nodes = $xc->findnodes( '/xml/element[@id=002]' );


for my $node ( $nodes->get_nodelist ) {
    say "Node: ", $node->nodeName;
    print "Attribute: ";
    print $_->getName, '=', $_->getValue, ' ' for    $node->attributes;
    say "";
}
+6  A: 

The primary reason for using XPathContext elements is namespaces. Your document has no namespaces so XPathContexts don't add anything to your query. Now, imagine that you actually had the following xml

my $doc = $parser->parse_string(<<EOT);
<?xml version="1.0"?>
<xml xmlns="http://my.company.com/ns/nsone" 
    xmlns:ns2="http://your.company.com/nstwo"&gt;
    Text im Dokument
    <ns2:element id="myID" name="myname" style="old" />
    <object objid="001" objname="Object1" />
    <element id="002" name="myname" />
</xml>
EOT 

You would need to define an XPathContext in order to have namespaces defined so that you could make namespace aware XPath queries:

my $root = $doc->documentElement;
my $xc = XML::LibXML::XPathContext->new( $root );
$xc->registerNs("ns2", "http://your.company.com/nstwo");
$xc->registerNs("ns1", "http://my.company.com/nsone");
my $nodes = $xc->findnodes( '/ns1:xml/ns2:element[@id="myID"]' );

Otherwise, you have no simple way to use namespace aware XPath statements.

Nic Gibson
'/ns1:xml/ns2:element[@id=002]': is ns2 a subset of ns1?
sid_com
Namespaces don't have a parent-child relationship. They're independent of each other. I wanted to demonstrate that you can have more than one namespace. In XPath, if you create a statement with no namespace you are asserting that you want elements with no namespace. In the sample doc I used, all elements are in a namespace, unprefixed elements are in the default namespace. However, you need to use a prefix in your XPath statement.
Nic Gibson