The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

XML::XSH2::XPathToXML - Generates XML document from XPath expressions

SYNOPSIS

  my @data = (
    '/project/name'         => 'The Ultimate Question',
    '/project/comment()'      => ' generated by XPathToXML ',
    '/project/start'        => '2002-09-08',
    '/project/end'          => '7002002-09-08',
    '/project/@id'          => '42',
    '/project/temp/pre'     => '41',
    '/project/temp/pre[position()=6]' => '46',
    '/project/temp/pre[3]'  => '43',
    '/project/temp/pre[2]'  => XML::LibXML->new->parse_xml_chunk(q(arbitrary <b>XML</b> chunk)),
  );

  my $xpx = new XML::XPathToXML( debug=>1 );

  $xpx->parse( \@data );

  $xpx->parse( '/project/temp/pre[last()]/@guess', 'tooHigh' );

  print $xpx->documentElement->toString(1)."\n";

Result:

  <project id="42">
    <!-- generated by XPathToXML -->
    <name>The Ultimate Question</name>
    <start>2002-09-08</start>
    <end>7002002-09-08</end>
    <temp>
      <pre>41</pre>
      <pre>arbitrary <b>XML</b> chunk</pre>
      <pre>43</pre>
      <pre/>
      <pre/>
      <pre guess="tooHigh">46</pre>
    </temp>
  </project>

DESCRIPTION

Generates an XML document or node tree from one or more XPath expressions. Returnes an XML::LibXML::Document or XML::LibXML::Element.

Only a limited subset of XPath is currently supported. Namely, the XPath expression must be a location path consisting of a /-separated sequence of one or more location steps along the child, sibling, or attribute axes. The node-test part of the expression cannot be neither a wildcard (*, @*, prefix:*, ...), nor the node() function. If a namespace prefix is used, then either the namespace must already be declared in the document or registered with an XPathContext object. Location steps may contain arbitrary predicates (filters), but see the details below.

The parser processes the location path as follows:

For an absolute location path (starting with /) the evaluation starts on the document node. For relative location path the evaluation starts on a specified initial context node. The parser evaluates the location path from left to right, one location step at a time, starting either on the document node (in case of absolute location path) or on a specified initial context node (in case of relative location paths). If the location step (including filters) matches a child node or an attribute of the current node, then the parser moves to the first node matched and to the next location step. If no nodes are matched by the location step, then the parser creates an element or attribute with the name (and possibly namespace) specified in the node-test part of the location step and tries again. If still no nodes are matched, the parser repeats the procedure until the location step matches or the number of sibling nodes created in this way reaches the limit specified in maximumAutoSiblings. In the first case the parser moves to the first matching node. In the latter case the parser fails (removing all sibling-nodes created for the failed location-step from the tree).

Hence, if a filter predicate of a location step specifies a position of a node (e.g. with [4], or [position3], etc), then the parser tries to automatically create empty siblings nodes until it finally creates one with for which the predicate is true.

Note, that because the parser only processes one location step at a time and always picks the first matching node, expressions like /root/a/b are treated as /root/a[1]/b[1]. So, in case of the document

  <root>
    <a/>
    <a>
      <b/> 
    </a>
  </root>

$xpx->parse(q(/root/a/b),'foo') will result in

  <root>
    <a><b>foo</b></a>
    <a>
      <b/>
    </a>
  </root>

although an element matching /root/a/b was already present in the document. To prevent this, either explicitly state that b must exist with /root/a[b]/b or set the second element a as the context node and use a relative location path such as b:

$xpx->setContextNode($xpc->document->find('/root/a[2]')->get_node(1)) $xpx->parse("b","foo"); # "./b" is also ok

or simply

$xpx->createNode("b","foo",$xpc->document->find('/root/a[2]')->get_node(1));

In the tradition of XML::LibXML errors must be trapped with eval() (the parser dies on error).

Methods

new(%args)

Generates a new XML::XPathToXML object.

Arguments:

version sets the XML version; default is "1.0".

encoding sets the XML encoding; default is none (meaning UTF8).

debug turns debugging on/off; default is off.

doc provide a XML::LibXML::Document to start with (rather than starting with an empty document)

node specify initial context node for relative XPath expressions

XPathContext specify XML::LibXML::XPathContext object to use for XPath evaluation (if not specified, then default LibXML's XPath support are used).

namespaces specify a hash mapping namespace prefixes to namespace URIs. This mapping is used to determine the correct namespace URI if an element or attribute with a prefix is auto-created. Note that if an XPathContext was specified that provides a lookupNs() method , then this module will also try to determine the namespace URIs from the namespace prefixes registered for the XPathContext.

maxAutoSiblings sets the maximum number of siblings that are automatically generated for a single XPath expression; default is 256.

parse( $hashref )
parse( $arrayref )
parse( $xpath, $value )

Parse XPath/value pairs and generate nodes.

createNode( $xpath, $value, $context_node? )

Like parse( $xpath, $value ) but returns the newly created node.

document()

Returns the document as an XML::LibXML::Document.

documentElement()

Returns the document element as an XML::LibXML::Element.

contextNode()

Returns the context node as an XML::LibXML::Node.

setContextNode( $node )

Set context to a given XML::LibXML::Node. This node is used as a context for relative XPath expressions.

reset( %args )

Resets the parser. Optionally, doc and node can be specified as in new().

close()

Closes the parser (forgetting current document and context node). After this you have to call init() before using the parser.

init()

Initiates the parser. Only needed after close().

AUTHOR

Kurt George Gjerde, version 0.05 by Petr Pajas

COPYRIGHT

2002 (c) InterMedia, University of Bergen.

Available under the same conditions as Perl.