xml-xalan-j-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Adrian Sutton" <adrian.sut...@ephox.com>
Subject Getting the context node list
Date Thu, 27 May 2004 01:34:05 GMT
Hi all,
(Sorry for the previous email, Outlook decided to send when I tried to
paste.  Go figure)

I'm looking for a way to get the complete context node list and am
generally not getting far.  I need the full context node list instead of
just the actual context node because I need to rerun XPath expressions
dynamically as the user changes the DOM, but can't run the entire XSLT
again because of performance issues.  I can get the XPath expression,
find the context node itself, find all the namespaces in effect, and
identify all the nodes which are used in the expression, I just can't
get the full context node list.  Without the full context node list,
functions like position() don't work correctly.

For the record, my current test expression is:
my:quantityOrdered * my:unitPrice

but the aim is to support any valid XPath expression.

My first approach was to look for an XPath function or XSLT element I
could use to get the full context node list but I haven't found
anything.

My second approach was to use a custom function and I've had some
success with that.  My currrent function is:

	public String getContext(ExpressionContext context) {
		StringBuffer buf = new StringBuffer();
		try {
			DTMIterator iter =
context.getXPathContext().getContextNodes();
			
			int handle = iter.getCurrentNode();
			if (handle != DTM.NULL) {
				Node n =
iter.getDTM(handle).getNode(handle);
				while (n != null) {
	
buf.append(XMLFilter.getIDFor(n));
					n = getNextNode(iter);
					if (n != null) {
						buf.append(",");
					}
				}
			}
		} catch (Exception e) {
			log.error("Failed to create context for xpath
expression.", e);
		}
		return buf.toString();
	}

XMLFilter.getIDFor(n) gives a String that can be used to retrieve the
node from the DOM later on (though various magic incantations we've
discovered).  For the first node in the context list this works
perfectly, unfortunately it appears that the DTMIterator I'm using is
the same one that Xalan is using and so the method causes Xalan to skip
over all but the first element (because getContext() has already
iterated through the nodes).  When I try to reset the position of the
iterator I get the exception:

This NodeSetDTM can not iterate to a previous
node!>java.lang.RuntimeException: This NodeSetDTM can not iterate to a
previous node!
	at
com.ephox.org.apache.xpath.axes.LocPathIterator.previousNode(LocPathIter
ator.java:627)
	at
com.ephox.org.apache.xpath.axes.NodeSequence.previousNode(NodeSequence.j
ava:364)
	at
com.ephox.org.apache.xpath.axes.NodeSequence.runTo(NodeSequence.java:485
)
	at
com.ephox.org.apache.xpath.axes.NodeSequence.setCurrentPos(NodeSequence.
java:499)
	at
com.ephox.editlive.java2.editor.xml.xpath.XPathExtensions.getContext(XPa
thExtensions.java:51)

I notice that there is a DTMIterator.setShouldCacheNodes(boolean) method
which enables random access to the iterator but calling it seems to
reset the iterator such that it no longer contains any nodes.  Is there
any property to set to make all iterators random access enabled?  I've
tried setting:

http://xml.apache.org/xalan/features/incremental
TransformerFactoryImpl.FEATURE_OPTIMIZE
and
http://xml.apache.org/xalan/features/optimize

to false with no success.

Alternately, is there some other approach I'm missing?

Regards,

Adrian Sutton.

Mime
View raw message