Project

Profile

Help

evaluation xpath on original dom tree

Added by Anonymous almost 16 years ago

Legacy ID: #5275540 Legacy Poster: Alex Hartmann (alex08)

Hello, we are evaluating an xpath expression on a dom tree from mozilla which contains proxies to the mozilla dom nodes. Currently we are using saxon 8 and everything works fine. Now I tried to upgrade to saxon 9 but with the api changes there is a new tree build for evaluating an xpath in certain cases. I tried this code: ================================================== XPathFactory xpf = new XPathFactoryImpl(); XPathEvaluator evaluator = (XPathEvaluator) xpf.newXPath(); Configuration config = evaluator.getStaticContext().getConfiguration(); evaluator.setStaticContext(new MyStandaloneContext(config)); evaluator.setXPathFunctionResolver(new MyXPathFunctionResolver()); evaluator.setNamespaceContext(new MyNamespaceContext(evaluator.getNamespaceContext())); DOMSource ds = new DOMSource(input); NodeInfo doc = evaluator.setSource(ds); XPathExpression xpe = evaluator.compile(xp); DOMNodeList nodeList = (DOMNodeList) xpe.evaluate(doc, XPathConstants.NODESET); ================================================== the problem is that evaluator.setSource already creates a new dom tree and our original tree is lost. Only in case the input Node is a document node the original tree is used. In this case setSource returns a DocumentWrapper and also xpe.evaluate returns the original element nodes. But if I pass any other element node to setSource, it always returns a TinyDocumentImpl and xpe.evaluate returns a list of ElementOverNodeInfo items. Is there a way to set the source other than a document node and still keep the original dom tree? regards, Alex


Replies (5)

Please register to reply

RE: evaluation xpath on original dom tree - Added by Anonymous almost 16 years ago

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

Sorry for the delay in replying. Unfortunately a number of these interfaces leave it unclear exactly under which circumstances you get a new tree and when you get a wrapper. There's also a bewildering variety of interfaces for running XPath within Saxon, for historic reasons: you're using the JAXP interface but with Saxon extensions, which is a combination I really wouldn't recommend as you get the disadvantages of both; these days I would say either use pure JAXP, or use s9api. The setSource() method under these conditions calls Configuration.buildDocument(), which always returns a document node. This means that when it's given a DOMSource, if the DOM node is a document node then it wraps it, but if it's an element then it copies the subtree rooted at that element to create a new document, and returns its document node. It would be better, I think, for setSource() always to wrap the node in the case of a DOMSource, and perhaps I will change it to do that. But in your situation, I think it would be better to control the wrapping yourself. To do this: (a) create a net.sf.saxon.dom.DocumentWrapper around the DOM Document node, using the constructor public DocumentWrapper(Node doc, String baseURI, Configuration config) { (You can get the Configuration from the XPathEvaluator) (b) wrap the "input" node using the wrap() method on the DocumentWrapper (c) supply the resulting NodeInfo object as the first argument to evaluate(). It might also work to supply the DOMSource directly as the first argument to evaluate(), I'm not sure without checking.

RE: evaluation xpath on original dom tree - Added by Anonymous almost 16 years ago

Legacy ID: #5311687 Legacy Poster: Alex Hartmann (alex08)

thanks for your reply, Michael. your suggestion works fine but I've one more problem with my extension function. This function searches for specific nodes starting from the current node. To get the current node I need the context which can be retrieved through the XPathContext. Therefor I implement XPathFunctionCall and the method "public SequenceIterator call(ValueRepresentation[] argValues, XPathContext context)" is called when my extension function is called. This works except that I do not know how I can transform my result (which is a DOMNodeList or List<Node>) to a SequenceIterator. Before switching to Saxon 9 this was possible with Value.convertJavaObjectToXPath but this method does no longer exist. I also tried your other suggestion to only use pure JAXP. Here I have the problem that there is no XPathFunctionCall and the XPathFunction interface only defines the method "evaluate(java.util.List args)" where I see no way how I could get the current node. What did I miss?

RE: evaluation xpath on original dom tree - Added by Anonymous almost 16 years ago

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

It might be simpler to pass the context node as an extra parameter to your extension function. But if you do want to override the call() method in XPathFunctionCall, I would have thought you could retain all the existing logic for converting the arguments and result - this shows exactly how to convert the extension function's result into a SequenceIterator: Object result = function.evaluate(convertedArgs); if (result == null) { return EmptyIterator.getInstance(); } JPConverter converter = JPConverter.allocate(result.getClass(), config); return Value.asIterator(converter.convert(result, context));

RE: evaluation xpath on original dom tree - Added by Anonymous almost 16 years ago

Legacy ID: #5317205 Legacy Poster: Alex Hartmann (alex08)

thanks for your help! I seems like we can finally upgrade to Saxon 9. I also thought about passing the context node as a parameter but for this we would have to change xpath expressions which are already stored in user scripts. Using the JPConverter works fine and was the missing class I was looking for.

    (1-5/5)

    Please register to reply