[Raku LibXML Project] / [LibXML Module] / XPath :: Context
class LibXML::XPath::Context
XPath Evaluation Context
Synopsis
use LibXML::XPath::Context;
use LibXML::Node;
my LibXML::XPath::Context $xpc .= new();
$xpc .= new(:$node, :suppress-warnings, :suppress-errors);
$xpc.registerNs($prefix, $namespace-uri);
# -OR-
$xpc .= new(:$node, :ns{ $prefix => $namespace-uri, });
# -OR-
my $raw = xmlXPathContext.new;
xpc .= new(:$raw);
$xpc.unregisterNs($prefix);
my Str $uri = $xpc.lookupNs($prefix);
$xpc.registerVarLookupFunc(&get-variable);
my &func = $xpc.getVarLookupFunc();
$xpc.unregisterVarLookupFunc;
$xpc.registerFunctionNS($name, $uri, &callback);
$xpc.unregisterFunctionNS($name, $uri);
$xpc.registerFunction($name, &callback);
$xpc.unregisterFunction($name);
my @nodes = $xpc.findnodes($xpath);
@nodes = $xpc.findnodes($xpath, $ref-node );
$node = $xpc.first($xpath);
$node = $xpc.last($xpath);
my LibXML::Node::Set $nodes = $xpc.findnodes($xpath, $ref-node );
my Any $object = $xpc.find($xpath );
$object = $xpc.find($xpath, $ref-node );
my $value = $xpc.findvalue($xpath );
my Bool $found = $xpc.exists( $xpath, $ref-node );
$xpc.contextNode = $node;
$node = $xpc.contextNode;
my Int $position = $xpc.contextPosition;
$xpc.contextPosition = $position;
my Int $size = $xpc.contextSize;
$xpc.contextSize = $size;
Description
The LibXML::XPath::Context class provides an almost complete interface to libxml2’s XPath implementation. With LibXML::XPath::Context, it is possible to evaluate XPath expressions in the context of arbitrary node, context size, and context position, with a user-defined namespace-prefix mapping, custom XPath functions written in Raku, and even a custom XPath variable resolver.
Examples
1. Namespaces
This example demonstrates registerNs()
method. It finds all paragraph nodes in an XHTML document.
my LibXML::XPath::Context $xc .= new: :doc($xhtml-doc);
$xc.registerNs('xhtml', 'http://www.w3.org/1999/xhtml');
my LibXML::Node @nodes = $xc.findnodes('//xhtml:p');
Alternatively, namespaces can be defined on the constructor:
my LibXML::XPath::Context $xc .= new: :doc($xhtml-doc), :ns{ xhtml => 'http://www.w3.org/1999/xhtml' };
my LibXML::Node @nodes = $xc.findnodes('//xhtml:p');
2. Custom XPath functions
This example demonstrates registerFunction()
method by defining a function filtering nodes based on a Raku regular expression:
sub grep-nodes(LibXML::Node::Set $nodes, Str $regex) {
$nodes.grep: {.textContent ~~ / <$regex> /};
};
# -OR-
sub grep-nodes(Array() $nodes, Str $regex) {
$nodes.grep: {.textContent ~~ / <$regex> /};
};
my LibXML::Document $doc .= parse: "example/article.xml";
$node = $doc.root;
my $xc = LibXML::XPath::Context.new(:$node);
$xc.registerFunction('grep-nodes', &grep-nodes);
@nodes = $xc.findnodes('grep-nodes(section,"^Bar")').list;
3. Variables
This example demonstrates registerVarLookup()
method. We use XPath variables to recycle results of previous evaluations:
sub var-lookup(Str $name, Str $uri, Hash $data) {
return $data{$name};
}
my $areas = LibXML.new.parse: :file('areas.xml');
my $empl = LibXML.new.parse: :file('employees.xml');
my $xc = LibXML::XPath::Context.new(node => $empl);
my %variables = (
A => $xc.find('/employees/employee[@salary>10000]'),
B => $areas.find('/areas/area[district='Brooklyn']/street'),
);
# get names of employees from $A working in an area listed in $B
$xc.registerVarLookupFunc(&var-lookup, %variables);
my @nodes = $xc.findnodes('$A[work_area/street = $B]/name');
Methods
method new
multi method new(LibXML::Document :$doc!, :%ns) returns LibXML::XPath::Context;
multi method new(LibXML::Node :$node, :%ns) returns LibXML::XPath::Context;
multi method new(xmlXPathContext :$raw) returns LibXML::XPath::Context;
Creates a new LibXML::XPath::Context object with an optional context document or node, and :%ns
, mapping of prefixes to namespace URI’s.
method registerNs
multi method registerNs(NCName:D :$prefix!, Str :$uri) returns 0
multi method registerNs(NCName:D $prefix!, Str $uri?) returns 0
multi method registerNs(LibXML::Namespace:D $ns) returns 0
Registers a namespace with a given prefix and uri.
A uri of Str:U will unregister any namespace with the given prefix.
method unregisterNs
multi method unregisterNs(NCName:D :$prefix!) returns 0
multi method unregisterNs(NCName:D $prefix!) returns 0
multi method unregisterNs(LibXML::Namespace:D $ns) returns 0
Unregisters a namespace with the given prefix
method lookupNs
method lookupNs(
Str:D $prefix where { ... }
) returns Str
Returns namespace URI registered with $prefix.
If $prefix
is not registered to any namespace URI returns Str:U
.
method registerVarLookupFunc
method registerVarLookupFunc(
&callback,
|args
) returns Mu
Registers a variable lookup function.
The registered function is executed by the XPath engine each time an XPath variable is evaluated. The callback function has two required arguments: $name
, variable name, and $uri
.
The function must return one value: Bool, Str, Numeric, LibXML::Node (e.g. Document, Element, etc.), LibXML::Node::Set or LibXML::Node::List.
For convenience, types: List, Seq and Slip can also be returned, these should contain only LibXML::Node objects.
Any additional arguments are captured and passed to the callback function. For example:
$xpc.registerVarLookupFunc(&my-callback, 'Xxx', :%vars);
matches the signature:
sub my-callback(Str $name, Str $uri, 'Xxx', :%vars!) {
...
}
method unregisterVarLookupFunc
method unregisterVarLookupFunc() returns Mu
Removes the variable lookup function. Disables variable lookup
method getVarLookupFunc
method getVarLookupFunc() returns Routine
Gets the current variable lookup function
method registerFunctionNS
method registerFunctionNS(
Str:D $name where { ... },
Str $uri,
&func,
|args
) returns Mu
Registers an extension function $name in $uri namespace
The arguments of the callback function are either simple scalars or LibXML::*
objects depending on the XPath argument types.
The function must return one value: Bool, Str, Numeric, LibXML::Node (e.g. Document, Element, etc.), LibXML::Node::Set or LibXML::Node::List.
For convenience, types: List, Seq and Slip can also be returned, these shoulf contain only LibXML::Node objects.
method unregisterFunctionNS
method unregisterFunctionNS(
Str:D $name where { ... },
Str $uri
) returns Mu
Unregisters extension function $name in $uri namespace.
method register-function
method register-function(
Str $url,
Str:D $name where { ... },
&func,
|c
) returns Mu
Like registerFunctionNS; same argument order as LibXSLT.register-function()
method registerFunction
method registerFunction(
Str:D $name where { ... },
&func,
|c
) returns Mu
Same as registerFunctionNS but without a namespace.
method unregisterFunction
method unregisterFunction(
Str:D $name where { ... }
) returns Mu
Same as unregisterFunctionNS but without a namespace.
method findnodes
multi method findnodes(LibXML::XPath::Expression:D $expr, LibXML::Node $ref?, Bool :$deref) returns LibXML::Node::Set;
multi method findnodes(Str:D $expr, LibXML::Node $ref?, Bool :$deref) returns LibXML::Node::Set;
# Examples
my LibXML::Node @nodes = $xpc.findnodes($xpath);
@nodes = $xpc.findnodes($xpath, $context-node );
my LibXML::Node::Set $nodes = $xpc.findnodes($xpath);
for $xpc.findnodes($xpath) { ... }
Performs the xpath statement on the current node and returns the result as an LibXML::Node::Set object.
Optionally, a node may be passed as a second argument to set the context node for the query.
The xpath expression can be passed either as a string, or as a LibXML::XPath::Expression object.
method first
multi method first(LibXML::XPath::Expression:D $expr, LibXML::Node $ref?) returns LibXML::Item;
multi method first(Str:D $expr, LibXML::Node $ref?) returns LibXML::Item;
my LibXML::Node $body = $doc.first('body');
The first
method is similar to findnodes
, except it returns a single node representing the first matching row. If no nodes were found, LibXML::Node:U
is returned.
method last
my LibXML::Node $last-row = $body.last('descendant::tr');
The last
method is similar to first
, except it returns the last rather than the first matching row.
method AT-KEY
method AT-KEY(
$_,
Bool :$deref = Bool::True
) returns LibXML::Node::Set
Alias for findnodes($_, :deref)
Example
my LibXML::XPath::Context $xpc .= new: :node($table-elem);
for $xpc<tr> -> LibXML::Element $row-elem {...}
method find
multi method find(LibXML::XPath::Expression:D $expr, LibXML::Node $ref?, Bool :$deref) returns Any;
multi method find(Str:D $expr, LibXML::Node $ref?, Bool :$deref) returns Any;
my Any $object = $xpc.find($xpath );
$object = $xpc.find($xpath, $context-node );
Finds nodes or values.
Performs the xpath expression using the current node as the context of the expression, and returns the result depending on what type of result the XPath expression had. For example, the XPath 1 * 3 + 52
results in a Numeric object being returned. Other expressions might return a Bool object, or a string. Optionally, a node may be passed as a second argument to set the context node for the query.
The xpath expression can be passed either as a string, or as a LibXML::XPath::Expression object.
method findvalue
multi method findvalue(LibXML::XPath::Expression:D $expr, LibXML::Node $ref?) returns Any;
multi method findvalue(Str:D $expr, LibXML::Node $ref?) returns Any;
Returns only a simple value as string, numeric or boolean.
An expression that would return an LibXML::Node::Set is coerced by calling string-value()
on each of its members and joing the result.
This could be used as the equivalent of <xsl:value-of select=``some-xpath’’/>.
Optionally, a node may be passed in the second argument to set the context node for the query.
The xpath expression can be passed either as a string, or as a LibXML::XPath::Expression object.
method exists
multi method exists(LibXML::XPath::Expression:D $expr, LibXML::Node $ref?) returns Bool;
multi method exists(Str:D $expr, LibXML::Node $ref?) returns Bool;
This method behaves like find, except that it only returns a Bool value (True if the expression matches a node, False otherwise) and may be faster than find, because the XPath evaluation may stop early on the first match.
For XPath expressions that do not return node-sets, the method returns True if the returned value is a non-zero number or a non-empty string.
method contextNode
method contextNode() returns LibXML::Node
Set or get the context node
method contextPosition
method contextPosition() returns Int
Set or get the current context position.
By default, this value is -1 (and evaluating XPath function position()
in the initial context raises an XPath error), but can be set to any value up to context size. This usually only serves to cheat the XPath engine to return given position when position()
XPath function is called.
Setting this value to -1 restores the default behavior.
method contextSize
method contextSize() returns Int
Set or get the current context size.
By default, this value is -1 (and evaluating XPath function last()
in the initial context raises an XPath error), but can be set to any non-negative value. This usually only serves to cheat the XPath engine to return the given value when last()
XPath function is called.
-
If context size is set to 0, position is automatically also set to 0.
-
If context size is positive, position is automatically set to 1. Setting context size to -1 restores the default behavior.
methods query-handler, querySelector, querySelectorAll
These methods provide pluggable support for CSS Selectors, as described in https://www.w3.org/TR/selectors-api/#DOM-LEVEL-2-STYLE.
The query handler is a third-party class or object that implements a method $.query-to-xpath(Str $selector --> Str) {...}
, that typically maps CSS selectors to XPath querys.
The handler may be configured globally:
# set up a global query selector. use the CSS::Selector::To::XPath module
use CSS::Selector::To::XPath;
use LibXML::Config;
LibXML::Config.query-handler = CSS::Selector::To::XPath.new;
# run queries
my LibXML::Document $doc .= new: string => q:to<\_(ツ)_/>;
<table id="score">
<thead>
<tr> <th>Test</th> <th>Result</th> </tr>
<thead>
<tbody>
<tr> <td>A</td> <td>87%</td> </tr>
<tr> <td>B</td> <td>78%</td> </tr>
<tr> <td>C</td> <td>81%</td> </tr>
</tbody>
<tfoot>
<tr> <th>Average</th> <td>82%</td> </tr>
</tfoot>
</table>
\_(ツ)_/
my $result-query = "#score>tbody>tr>td:nth-of-type(2)"
my @abc-results = $document.querySelectorAll($result-query);
my $a-result = $document.querySelector($result-query);
methods set-options, suppress-warnings, suppress-errors
my LibXML::XPath::Context $ctx .= new: :suppress-warnings;
$ctx.suppress-errors = True;
XPath Contexts have some Boolean error handling options:
-
suppress-warnings
- Don’t report warnings -
suppress-errors
- Don’t report or handle errors
Copyright
2001-2007, AxKit.com Ltd.
2002-2006, Christian Glahn.
2006-2009, Petr Pajas.
License
This program is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 http://www.perlfoundation.org/artistic_license_2_0.