Project

Profile

Help

Effecient way of wrapping an XdmNode to doc

Added by Anonymous almost 16 years ago

Legacy ID: #5071339 Legacy Poster: David Lee (daldei)

What is the suggested way of wrapping/converting an XdmNode to a document suitable as the context for XQuery/Xslt and XPath. I have a XdmValue which is the result of a previous XQuery or possibly DocumentBuilder.build. If this is a XdmNode e.g. XdmItem item = ... if( item instanceof XdmNode ) then I'd like to set it as the context for an XQuery / Xslt or Xpath. I tried with XQuery and if the item is not a document then the xquery crashes out. I tried calling DocumentBuilder.wrap() and it crashes with a null pointer (the external model was not found). I got this to work with the following if( item instanceof XdmNode ) context = builder.build(((XdmNode)item).asSource()); But stepping through the code it appears as if the entire tree is parsed and recreated. If I want to perform many xquery's on the same context that is highly inefficient. Is there a way to "wrap" an XdmNode so that it works as a document for Xquery/Xslt/Xpath contexts without having this overhead ? Maybe some magic way of creating a DocumentImpl on top of this node ? Thanks for any suggestions -David


Replies (9)

Please register to reply

RE: Effecient way of wrapping an XdmNode to d - Added by Anonymous almost 16 years ago

Legacy ID: #5071512 Legacy Poster: Michael Kay (mhkay)

If you stay within the s9api environment, then you can use the XdmNode directly, for example methods like XPathSelector.setContextItem() XPathSelector.setVariable() XQueryEvaluator.setContextItem() XQueryEvaluator.setExternalVariable() will all take an XdmNode as input (because an XdmNode is an XdmItem and an XdmValue). If you need to escape into lower-level interfaces that want a NodeInfo or DocumentInfo as input, then you can use XdmNode.getUnderlyingNode() (because an XdmNode is just a wrapper for a NodeInfo). Michael Kay Saxonica

RE: Effecient way of wrapping an XdmNode to d - Added by Anonymous almost 16 years ago

Legacy ID: #5071567 Legacy Poster: David Lee (daldei)

I tried doing this and it doesnt work for me. XQueryEvaluator.setContextItem() threw an exception because the node i had was not a document, but rather just a TinyTree node. Thats why I'm looking for a way to convert it to a document so setContextItem() will work with it. -David

RE: Effecient way of wrapping an XdmNode to d - Added by Anonymous almost 16 years ago

Legacy ID: #5071774 Legacy Poster: Michael Kay (mhkay)

>I tried doing this and it doesnt work for me. You need to tell me exactly what you did and exactly how it failed, then I can help you. Show me your code, show me the stack trace. Michael Kay Saxonica

RE: Effecient way of wrapping an XdmNode to d - Added by Anonymous almost 16 years ago

Legacy ID: #5071874 Legacy Poster: David Lee (daldei)

Here is a minimal case that shows the problem: Similar problems exist even if the context of the first xquery is a document. public class Main { public static void main(String args[]) throws SaxonApiException { Processor processor = new Processor(false); /* * Create a simple value from xquery */ XQueryCompiler compiler = processor.newXQueryCompiler(); XQueryExecutable expr = compiler.compile("<foo/>"); XQueryEvaluator eval = expr.load(); XdmValue value = eval.evaluate(); // prove it worked System.out.println("value is: " + value.toString()); // try to set the value as the context for a new xquery expr = compiler.compile("/"); eval = expr.load(); eval.setContextItem( (XdmItem) value ); // EXCEPTION HERE XdmValue value2 = eval.evaluate(); System.out.println("value2 is: " + value2.toString()); } } Exception: (tested with Saxon 9.1 today) Error on line 1 of module with no systemId: XPDY0050: The root of the tree containing the context item is not a document node Exception in thread "main" net.sf.saxon.s9api.SaxonApiException: The root of the tree containing the context item is not a document node at net.sf.saxon.s9api.XQueryEvaluator.evaluate(XQueryEvaluator.java:293) at Main.main(Main.java:41) Caused by: net.sf.saxon.trans.XPathException: The root of the tree containing the context item is not a document node at net.sf.saxon.expr.Expression.dynamicError(Expression.java:967) at net.sf.saxon.expr.RootExpression.getNode(RootExpression.java:72) at net.sf.saxon.expr.SingleNodeExpression.iterate(SingleNodeExpression.java:110) at net.sf.saxon.query.XQueryExpression.iterator(XQueryExpression.java:307) at net.sf.saxon.s9api.XQueryEvaluator.evaluate(XQueryEvaluator.java:281) ... 1 more

RE: Effecient way of wrapping an XdmNode to d - Added by Anonymous almost 16 years ago

Legacy ID: #5071949 Legacy Poster: Michael Kay (mhkay)

That's a straightforward error in your query, nothing to do with the calling Java application. The expression "/" is defined to raise error XPDY0050 if the context item is an element in a tree that has no document node at its root (which it is). If you want this to work, change the first query to XQueryExecutable expr = compiler.compile("document{<foo/>}"); or change the second query to use "root()" rather than "/". Michael Kay http://www.saxonica.com/

RE: Effecient way of wrapping an XdmNode to d - Added by Anonymous almost 16 years ago

Legacy ID: #5071959 Legacy Poster: Michael Kay (mhkay)

Actually I think you've fallen into a bit of an elephant trap. So many example queries are written in the form <a>{ some expression }</a> and they work fine when the result is serialized to lexical XML, because the serializer adds a document node automatically. But when the tree produced by this query is input to another query, which will often be the case in real applications, then it makes a real difference that there is no document node present, and you should probably get into the habit of creating it explicitly: document{<a>{ some expression }</a>}

RE: Effecient way of wrapping an XdmNode to d - Added by Anonymous almost 16 years ago

Legacy ID: #5072039 Legacy Poster: David Lee (daldei)

Thanks! I now get whats going on. But ... unfortunatly my particular problem still exists. I cannot easily universally enforce that all xquery's use "document{ ... }", because I need the ability to produce sequences directly say "1,2,3" and automatically wrapping them in document{} means I dont get sequences as the result ... so I'm probably screwed both ways. Is there a Saxon-way of programatically wrapping an XdmItem with a "document" node so I can treat oprhan'd nodes as documents ? I could certianly run a xquery document { $variable } but that seems an unnecessary overhead. Thanks again for your suggestions ! I did find if I changed my test code to use "." instead of "/" it worked great, proving I dont HAVE to supply documents as the context to xquery.

RE: Effecient way of wrapping an XdmNode to d - Added by Anonymous almost 16 years ago

Legacy ID: #5072059 Legacy Poster: Michael Kay (mhkay)

>Is there a Saxon-way of programatically wrapping an XdmItem with a "document" node so I can treat oprhan'd nodes as documents ? Well, the simplest way is probably to run the query document{.} Any way of doing it will involve making a copy of the node, which is going to be expensive. If you can't change the first query to produce a document node, then you have to change your second query so it doesn't expect one. Beyond that, I'm afraid I don't know enough about your requirements, and can't design your application for you.

RE: Effecient way of wrapping an XdmNode to d - Added by Anonymous almost 16 years ago

Legacy ID: #5072164 Legacy Poster: David Lee (daldei)

Thanks a lot. No need for you to design my application :) I'm just trying to figure out what works and what doesnt. In this case both the queries are user specified so I have no (or little) control over them, although in theory I can prepend them with arbitrary text, but then that takes some ESP work to determine what was intended. I think I understand whats going on now and it should work fine "as is". Thanks ! -David

    (1-9/9)

    Please register to reply