All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.saxon.expr.PathMap Maven / Gradle / Ivy

Go to download

Provides a basic XSLT 2.0 and XQuery 1.0 processor (W3C Recommendations, January 2007). Command line interfaces and implementations of several Java APIs (DOM, XPath, s9api) are also included.

The newest version!
package net.sf.saxon.expr;

import net.sf.saxon.Configuration;
import net.sf.saxon.trans.XPathException;
import net.sf.saxon.functions.Document;
import net.sf.saxon.functions.SystemFunction;
import net.sf.saxon.functions.Doc;
import net.sf.saxon.query.StaticQueryContext;
import net.sf.saxon.query.XQueryExpression;
import net.sf.saxon.pattern.NodeKindTest;
import net.sf.saxon.pattern.AnyNodeTest;
import net.sf.saxon.om.Axis;
import net.sf.saxon.sxpath.XPathEvaluator;
import net.sf.saxon.sxpath.XPathExpression;

import java.io.PrintStream;
import java.io.FileReader;
import java.io.File;
import java.util.*;
import java.net.URISyntaxException;
import java.net.URI;

/**
 * A PathMap is a description of all the paths followed by an expression.
 * It is a set of trees. Each tree contains as its root an expression that selects
 * nodes without any dependency on the context. The arcs in the tree are axis steps.
 * So the expression doc('a.xml')/a[b=2]/c has a single root (the call on doc()), with
 * a single arc representing child::a, this leads to a node which has two further arcs
 * representing child::b and child::c. Because element b is atomized, there will also be
 * an arc for the step descendant::text() indicating the requirement to access the text
 * nodes of the element.
 *
 * 

The current implementation works only for XPath 2.0 expressions (for example, constructs * like xsl:for-each-group are not handled.)

* *

This class, together with the overloaded method * {@link Expression#addToPathMap(PathMap, net.sf.saxon.expr.PathMap.PathMapNodeSet)} can be * seen as an implementation of the static path analysis algorithm given in section 4 of * A. Marian and J. Simeon, * Projecting XML Documents, VLDB 2003.

*/ public class PathMap { private List pathMapRoots = new ArrayList(); // a list of PathMapRoot objects private HashMap pathsForVariables = new HashMap(); // a map from a variable Binding to a PathMapNodeSet /** * A node in the path map. A node holds a set of arcs, each representing a link to another * node in the path map. */ public static class PathMapNode { List arcs; // a list of PathMapArcs private boolean returnable; private boolean atomized; private boolean hasUnknownDependencies; /** * Create a node in the PathMap (initially with no arcs) */ private PathMapNode() { arcs = new ArrayList(); } /** * Create a new arc * @param step the AxisExpression representing this step * @return the newly-constructed target of the new arc */ public PathMapNode createArc(AxisExpression step) { for (int i=0; i=0; i--) { PathMapArc arc = (PathMapArc)root.arcs.get(i); byte axis = arc.getStep().getAxis(); switch (axis) { case Axis.ATTRIBUTE: case Axis.NAMESPACE: { AxisExpression newStep = new AxisExpression(Axis.DESCENDANT, NodeKindTest.ELEMENT); PathMapNode newTarget = new PathMapNode(); newTarget.arcs.add(arc); newRoot.createArc(newStep, newTarget); break; } default: { AxisExpression newStep = new AxisExpression( Axis.DESCENDANT_OR_SELF, arc.getStep().getNodeTest()); newRoot.createArc(newStep, arc.getTarget()); break; } } } for (int i=0; i=0; i--) { PathMapArc thisArc = (PathMapArc)node.arcs.get(i); AxisExpression axisStep = thisArc.getStep(); PathMapNode grandParent = (nodeStack.size() < 2 ? null : (PathMapNode)nodeStack.get(nodeStack.size()-2)); byte lastAxis = -1; if (grandParent != null) { for (Iterator iter = grandParent.arcs.iterator(); iter.hasNext(); ) { PathMapArc arc = ((PathMapArc)iter.next()); if (arc.getTarget() == node) { lastAxis = arc.getStep().getAxis(); } } } switch (axisStep.getAxis()) { case Axis.ANCESTOR_OR_SELF: case Axis.DESCENDANT_OR_SELF: if (axisStep.getNodeTest() == NodeKindTest.DOCUMENT) { // This is typically an absolute path expression appearing within a predicate node.arcs.remove(i); for (Iterator iter = thisArc.getTarget().arcs.iterator(); iter.hasNext(); ) { root.arcs.add(iter.next()); } break; } else { // fall through } case Axis.ANCESTOR: case Axis.FOLLOWING: case Axis.PRECEDING: { // replace the axis by a downwards axis from the root if (axisStep.getAxis() != Axis.DESCENDANT_OR_SELF) { AxisExpression newStep = new AxisExpression(Axis.DESCENDANT_OR_SELF, axisStep.getNodeTest()); newStep.setContainer(axisStep.getContainer()); root.createArc(newStep, thisArc.getTarget()); node.arcs.remove(i); } break; } case Axis.ATTRIBUTE: case Axis.CHILD: case Axis.DESCENDANT: case Axis.NAMESPACE: // no action break; case Axis.FOLLOWING_SIBLING: case Axis.PRECEDING_SIBLING: { if (grandParent != null) { AxisExpression newStep = new AxisExpression(lastAxis, axisStep.getNodeTest()); newStep.setContainer(axisStep.getContainer()); grandParent.createArc(newStep, thisArc.getTarget()); node.arcs.remove(i); break; } else { AxisExpression newStep = new AxisExpression(Axis.CHILD, axisStep.getNodeTest()); newStep.setContainer(axisStep.getContainer()); root.createArc(newStep, thisArc.getTarget()); node.arcs.remove(i); break; } } case Axis.PARENT: { if (lastAxis == Axis.CHILD || lastAxis == Axis.ATTRIBUTE || lastAxis == Axis.NAMESPACE) { // ignore the parent step - it leads to somewhere we have already been. // But it might become a returned node if (node.isReturnable()) { grandParent.setReturnable(true); } // any paths after the parent step need to be attached to the grandparent PathMapNode target = thisArc.getTarget(); for (int a=0; a




© 2015 - 2025 Weber Informatics LLC | Privacy Policy