Bug #5727
Updated by Michael Kay about 2 years ago
Xquery outputing a complex element does not work with domino, if xml has any attribute that is not namespace aware or its created with a document builder that’s not namespace aware. This seems to be because Node.getlocalName() does not have an implementation for Domino nodes, similar to whats present for TinyTree and DOMWrapper. ``` DomWrapper: public static String getLocalName(Node node) { /* 349 */ String s = node.getLocalName(); /* 350 */ if (s == null) { /* */ /* 352 */ String n = node.getNodeName(); /* 353 */ int colon = n.indexOf(58); /* 354 */ return colon >= 0 ? n.substring(colon + 1) : n; /* */ /* */ /* */ /* */ } else { /* 359 */ return s; /* */ } /* */ } TinyTree: public String getLocalPart() { /* 176 */ return this.tree.getNamePool().getLocalName(this.tree.attCode[this.nodeNr]); /* */ } Domino: /* */ public String getLocalPart() { /* 214 */ return this.domAttr.getLocalName(); /* */ } /** * Introduced in DOM Level 2. <p> * * Returns the local part of the qualified name of this node. * For nodes created with a DOM Level 1 method, such as createElement * from the Document interface, and for nodes of any type other than * ELEMENT_NODE and ATTRIBUTE_NODE this is the same as the nodeName * attribute. * @since WD-DOM-Level-2-19990923 * @see AttrNSImpl * @see ElementNSImpl */ public String getLocalName() { return null; } ``` ``` Example: public class XqueryTestBug { static String htdQuery = "<a>{(.)/htd:task}</a>"; static boolean useDomino = true; public static void main(String argv[]) throws Exception { try { run(argv[0]); } catch (SaxonApiException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private static void run(String xmlFile) throws SaxonApiException, IOException, Exception { // the Saxon processor object String queryString = htdQuery; EnterpriseConfiguration pc = setupSaxonAndGetConfig(); pc.registerExternalObjectModel(DOMEnvelope.getInstance()); pc.registerExternalObjectModel(DOMObjectModel.getInstance()); Processor saxon = new Processor(pc); XQueryCompiler compiler = saxon.newXQueryCompiler(); compiler.declareNamespace("htd", "http://www.example.org/WS-HT"); compiler.declareNamespace("trt", "http://schemas.active-endpoints.com/b4p/wshumantask/2007/10/aeb4p-task-rt.xsd"); compiler.declareNamespace("tlc", "http://schemas.active-endpoints.com/b4p/wshumantask/2007/10/aeb4p-task-lifecycle-wsdl.xsd"); compiler.declareNamespace("sf", "http://schemas.active-endpoints.com/appmodules/screenflow/2010/10/avosScreenflow.xsd"); XQueryExecutable exec = compiler.compile(queryString); XQueryEvaluator query = exec.load(); //load document String input = FileUtils.readFileToString(new File(xmlFile)); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); javax.xml.parsers.DocumentBuilder documentBuilder = factory.newDocumentBuilder(); InputSource inputSource = new InputSource(new StringReader(input)); org.w3c.dom.Document doc = documentBuilder.parse(inputSource); if(useDomino) { DominoTree domTree = DominoTree.makeTree(doc.getDocumentElement().getOwnerDocument(), pc, "systemID"); SequenceIterator next = domTree.getRootNode().iterateAxis(AxisInfo.CHILD,NodeKindTest.ELEMENT); GroundedValue gv = SequenceTool.toGroundedValue(next); DominoNode elNode = (DominoNode) gv.itemAt(0); query.setContextItem( (XdmNode) XdmValue.wrap(gv)); } else { TransformerFactory tfactory = new EnterpriseTransformerFactory(pc); final Transformer transformer = tfactory.newTransformer(); PipelineConfiguration pipeconfig = pc.makePipelineConfiguration(); // set up holder for the output final TinyBuilder outputTarget = new TinyBuilder( pipeconfig); transformer.transform(new DOMSource(doc), outputTarget); TinyTree tt = outputTarget.getTree(); NodeInfo nodeInfo = tt.getRootNode(); query.setContextItem(new XdmNode(nodeInfo)); } XdmValue result = query.evaluate(); } } ``` Exception seen with Domino: ``` Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because the return value of "net.sf.saxon.om.NodeName.getLocalPart()" is null at net.sf.saxon.om.NameOfNode.equals(NameOfNode.java:177) at net.sf.saxon.om.SingletonAttributeMap.put(SingletonAttributeMap.java:69) at net.sf.saxon.om.NodeInfo.attributes(NodeInfo.java:482) at net.sf.saxon.tree.util.Navigator.copy(Navigator.java:678) at net.sf.saxon.om.NodeInfo.copy(NodeInfo.java:522) at net.sf.saxon.event.ComplexContentOutputter.decompose(ComplexContentOutputter.java:893) at net.sf.saxon.event.ComplexContentOutputter.append(ComplexContentOutputter.java:658) at net.sf.saxon.expr.Expression.lambda$process$0(Expression.java:948) at net.sf.saxon.om.SequenceTool.supply(SequenceTool.java:147) at net.sf.saxon.expr.Expression.process(Expression.java:948) at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:357) at net.sf.saxon.expr.instruct.ElementCreator.processLeavingTail(ElementCreator.java:298) at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:142) at net.sf.saxon.expr.parser.ExpressionTool.getIteratorFromProcessMethod(ExpressionTool.java:678) at net.sf.saxon.expr.instruct.Instruction.iterate(Instruction.java:374) at com.saxonica.ee.bytecode.ByteCodeCandidate.iterate(ByteCodeCandidate.java:328) at net.sf.saxon.query.XQueryExpression.iterator(XQueryExpression.java:378) at net.sf.saxon.s9api.XQueryEvaluator.evaluate(XQueryEvaluator.java:520) at XqueryTest.runStatic(XqueryTest.java:474) at XqueryTest.run(XqueryTest.java:140) at XqueryTest.main(XqueryTest.java:116) ```