/** * Get n'th attribute (DOM NamedNodeMap method). In this implementation we number the attributes * as follows: 0 - the xmlns:xml namespace declaration 1-n further namespace declarations n+1... * "real" attribute declarations */ public Node item(int index) { if (index < 0) { return null; } if (index == 0) { NamespaceIterator.NamespaceNodeImpl nn = new NamespaceIterator.NamespaceNodeImpl(parent, NamespaceConstant.XML_NAMESPACE_CODE, 0); return NodeOverNodeInfo.wrap(nn); } int nscount = getNumberOfNamespaces(); if (index < nscount) { int[] buffer = new int[8]; int[] nsList = parent.getDeclaredNamespaces(buffer); int nscode = nsList[index - 1]; NamespaceIterator.NamespaceNodeImpl nn = new NamespaceIterator.NamespaceNodeImpl(parent, nscode, index); return NodeOverNodeInfo.wrap(nn); } int pos = 0; int attNr = (index - nscount); AxisIterator atts = parent.iterateAxis(Axis.ATTRIBUTE); while (true) { NodeInfo att = (NodeInfo) atts.next(); if (att == null) { return null; } if (pos == attNr) { return NodeOverNodeInfo.wrap(att); } pos++; } }
@Override public String convert(NodeInfo source) { switch (source.getNodeKind()) { case Node.DOCUMENT_NODE: return ""; case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE: return "text()"; case Node.COMMENT_NODE: return "comment()"; case Node.PROCESSING_INSTRUCTION_NODE: return "processing-instruction('" + source.getDisplayName() + "')"; case Node.ELEMENT_NODE: String prefix = nsContext.getPrefix(source.getURI()); String name = source.getLocalPart(); return StringUtil.isEmpty(prefix) ? name : prefix + ':' + name; case Node.ATTRIBUTE_NODE: if (Namespaces.URI_XMLNS.equals(source.getURI())) return "namespace::" + source.getLocalPart(); prefix = nsContext.getPrefix(source.getURI()); name = source.getLocalPart(); return '@' + (StringUtil.isEmpty(prefix) ? name : prefix + ':' + name); case NodeType.NAMESPACE: return "namespace::" + source.getLocalPart(); default: return null; } }
/** * Set all the declared namespaces to be the namespaces that are in-scope for a given node. In * addition, the standard namespaces (xml, xslt, saxon) are declared. * * @param node The node whose in-scope namespaces are to be used as the context namespaces. Note * that this will have no effect unless this node is an element. */ public void setNamespaces(NodeInfo node) { namespaces.clear(); AxisIterator iter = node.iterateAxis(Axis.NAMESPACE); while (true) { NodeInfo ns = (NodeInfo) iter.next(); if (ns == null) { return; } declareNamespace(ns.getLocalPart(), ns.getStringValue()); } }
/** * Provide information about the node being copied. This method is called immediately before the * startElement call for the element node in question. * * @param element the node being copied, which must be an element node */ public int notifyElementNode(NodeInfo element) { systemId = (wholeDocument ? element.getSystemId() : element.getBaseURI()); // The logic behind this is that if we are copying the whole document, we will be copying all // the relevant xml:base attributes; so retaining the systemId values is sufficient to enable // the base URIs of the nodes to be preserved. But if we only copy an element (for example // an xsl:import-schema element - see test schema091 - then its base URI might be affected // by xml:base attributes that aren't being copied. Ideally we would have two separate // properties, // but XDM doesn't work that way. lineNumber = element.getLineNumber(); return 0; }
/** Get number of attributes and namespaces (DOM NamedNodeMap method). */ public int getLength() { int length = 0; AxisIterator atts = parent.iterateAxis(Axis.ATTRIBUTE); while (atts.next() != null) { length++; } return getNumberOfNamespaces() + length; }
/** * Create a StandaloneContext using a specific Node. This node is used to initialize the NamePool * and also to establish the initial set of in-scope namespaces */ public StandaloneContext(NodeInfo node) { DocumentInfo doc = node.getDocumentRoot(); if (doc == null) { throw new IllegalArgumentException( "The node used to establish a standalone context must be in a tree whose root is a document node"); } namePool = doc.getNamePool(); setNamespaces(node); }
@Override public String convert(NodeInfo source) { switch (source.getNodeKind()) { case NodeType.ATTRIBUTE: case NodeType.NAMESPACE: return delegate.convert(source); } return super.convert(source); }
public static void assertXPathEquals( String xpathString, Document doc, boolean ignoreOrder, Object... expectedValues) { try { XPathEvaluator xpathEvaluator = new XPathEvaluator(); XPathExpression expr = xpathEvaluator.createExpression(xpathString); final JDOMSource docAsDomSource = new JDOMSource(doc); List nodes = expr.evaluate(docAsDomSource); if (nodes.size() != expectedValues.length) { org.junit.Assert.fail( "expected " + expectedValues.length + " values at xpath: " + xpathString); } String[] actualValues = new String[nodes.size()]; for (int i = 0; i < expectedValues.length; i++) { Object node = nodes.get(i); if (node instanceof NodeInfo) { NodeInfo nodeInfo = (NodeInfo) node; actualValues[i] = nodeInfo.getStringValue(); } else { actualValues[i] = String.valueOf(node); } } String[] expectedValuesAsString = new String[expectedValues.length]; for (int i = 0; i < expectedValues.length; i++) { expectedValuesAsString[i] = String.valueOf(expectedValues[i]); } if (ignoreOrder) { Arrays.sort(actualValues); Arrays.sort(expectedValuesAsString); } org.junit.Assert.assertArrayEquals(expectedValuesAsString, actualValues); } catch (Exception e) { throw new RuntimeException(e); } }
/** Get named attribute (DOM NamedNodeMap method) */ public Node getNamedItemNS(String uri, String localName) { if (uri == null) { uri = ""; } if (NamespaceConstant.XMLNS.equals(uri)) { return getNamedItem("xmlns:" + localName); } if (uri.equals("") && localName.equals("xmlns")) { return getNamedItem("xmlns"); } AxisIterator atts = parent.iterateAxis(Axis.ATTRIBUTE); while (true) { NodeInfo att = (NodeInfo) atts.next(); if (att == null) { return null; } if (uri.equals(att.getURI()) && localName.equals(att.getLocalPart())) { return NodeOverNodeInfo.wrap(att); } } }
@Override @SuppressWarnings({"unchecked"}) public List<?> translate(Object result, NamespaceContext nsContext) { List nodeList = (List) result; int i = 0; for (Object item : nodeList) { if (item instanceof List) nodeList.set(i, translate(item, nsContext)); else { NodeInfo node = (NodeInfo) item; int type = node.getNodeKind(); String value = ""; if (type != NodeType.DOCUMENT && type != NodeType.ELEMENT) value = node.getStringValue(); String localName = node.getLocalPart(); String namespaceURI = node.getURI(); String qualifiedName = node.getDisplayName(); String location = SaxonNavigator.INSTANCE.getXPath(node, nsContext); NodeItem nodeItem = new NodeItem(type, location, value, localName, namespaceURI, qualifiedName); nodeItem.xml = node; nodeList.set(i, nodeItem); } i++; } return nodeList; }
private String serialize(final Object o, final String method, final boolean includeProlog) throws XPathException { if (o instanceof NodeInfo) { final NodeInfo nodeInfo = ((NodeInfo) o); final Configuration config = nodeInfo.getConfiguration(); final StringWriter sw = new StringWriter(); final Properties props = new Properties(); props.setProperty("method", method); props.setProperty("indent", "no"); if (!includeProlog) { props.setProperty("omit-xml-declaration", "yes"); } else { props.setProperty("omit-xml-declaration", "no"); } final Receiver serializer = config .getSerializerFactory() .getReceiver(new StreamResult(sw), config.makePipelineConfiguration(), props); nodeInfo.copy(serializer, NodeInfo.ALL_NAMESPACES, true, 0); return sw.toString(); } return null; }
/** Get the number of declared namespaces */ private int getNumberOfNamespaces() { if (numberOfNamespaces == -1) { int[] buffer = new int[8]; int[] nsList = parent.getDeclaredNamespaces(buffer); int count = nsList.length; for (int i = 0; i < count; i++) { if (nsList[i] == -1) { count = i; break; } } numberOfNamespaces = count + 1; // +1 for the XML namespace } return numberOfNamespaces; }
@Override public void write(NodeInfo node, String uri) { UpdateHandler updateHandler = core.getUpdateHandler(); // Create a version of the document for saving to the transaction log, // or for cloud update via HTTP SolrInputDocument solrDoc = new SolrInputDocument(); solrDoc.addField(uriFieldName, uri); if (isCloud()) { // TODO: write as binary, but we need to enable the binary update request writer for this // TinyBinary tinybin = new TinyBinary(((TinyNodeImpl)node).getTree()); // solrDoc.addField(xmlFieldName, tinybin.getByteBuffer().array()); Serializer serializer = xqueryComponent.solrIndexConfig.checkoutSerializer(); try { String xmlString = serializer.serializeNodeToString(new XdmNode(node)); solrDoc.addField(xmlFieldName, xmlString); } catch (SaxonApiException e) { throw new LuxException(e); } finally { xqueryComponent.solrIndexConfig.returnSerializer(serializer); } // TODO -- if we can determine this doc only gets added locally?? // solrDoc.addField(xmlFieldName, node); } else if (updateHandler.getUpdateLog() != null) { if (node instanceof TinyNodeImpl) { TinyBinary tinybin = new TinyBinary(((TinyNodeImpl) node).getTree()); solrDoc.addField(xmlFieldName, tinybin.getByteBuffer()); } else { String xml = node.toString(); solrDoc.addField(xmlFieldName, xml); } } if (isCloud()) { writeToCloud(solrDoc, uri); } else { writeLocal(solrDoc, node, uri); } }
/** Get named attribute (DOM NamedNodeMap method) */ public Node getNamedItem(String name) { if (name.equals("xmlns")) { int[] nsarray = parent.getDeclaredNamespaces(null); for (int i = 0; i < nsarray.length; i++) { if (nsarray[i] == -1) { return null; } else if (((nsarray[i] >> 16) & 0xffff) == 0) { NamespaceIterator.NamespaceNodeImpl nn = new NamespaceIterator.NamespaceNodeImpl(parent, nsarray[i], i + 1); return NodeOverNodeInfo.wrap(nn); } } return null; } else if (name.startsWith("xmlns:")) { String prefix = name.substring(6); if (prefix.equals("xml")) { NamespaceIterator.NamespaceNodeImpl nn = new NamespaceIterator.NamespaceNodeImpl(parent, NamespaceConstant.XML_CODE, 0); return NodeOverNodeInfo.wrap(nn); } int[] buffer = new int[8]; int[] nsarray = parent.getDeclaredNamespaces(buffer); for (int i = 0; i < nsarray.length; i++) { if (nsarray[i] == -1) { return null; } else if (prefix.equals(parent.getNamePool().getPrefixFromNamespaceCode(nsarray[i]))) { NamespaceIterator.NamespaceNodeImpl nn = new NamespaceIterator.NamespaceNodeImpl(parent, nsarray[i], i + 1); return NodeOverNodeInfo.wrap(nn); } } return null; } else { AxisIterator atts = parent.iterateAxis(Axis.ATTRIBUTE); while (true) { NodeInfo att = (NodeInfo) atts.next(); if (att == null) { return null; } if (name.equals(att.getDisplayName())) { return NodeOverNodeInfo.wrap(att); } } } }
public static boolean isNamespaceDeclaration(NodeInfo attr) { return Namespaces.URI_XMLNS.equals(attr.getURI()) || attr instanceof NamespaceIterator.NamespaceNodeImpl; }
/** Enumerate the results of the expression */ public SequenceIterator iterate(XPathContext context) throws XPathException { Controller controller = context.getController(); Item arg2; try { arg2 = argument[2].evaluateItem(context); } catch (XPathException e) { if ("XPDY0002".equals(e.getErrorCodeLocalPart())) { dynamicError( "Cannot call the key() function when there is no context item", "XTDE1270", context); return null; } else if ("XPDY0050".equals(e.getErrorCodeLocalPart())) { dynamicError( "In the key() function," + " the node supplied in the third argument (or the context node if absent)" + " must be in a tree whose root is a document node", "XTDE1270", context); return null; } else if ("XPTY0020".equals(e.getErrorCodeLocalPart())) { dynamicError( "Cannot call the key() function when the context item is an atomic value", "XTDE1270", context); return null; } throw e; } NodeInfo origin = (NodeInfo) arg2; NodeInfo root = origin.getRoot(); if (root.getNodeKind() != Type.DOCUMENT) { dynamicError( "In the key() function," + " the node supplied in the third argument (or the context node if absent)" + " must be in a tree whose root is a document node", "XTDE1270", context); return null; } DocumentInfo doc = (DocumentInfo) root; int fprint = keyFingerprint; if (fprint == -1) { String givenkeyname = argument[0].evaluateItem(context).getStringValue(); try { fprint = controller .getNamePool() .allocateLexicalQName( givenkeyname, false, nsContext, controller.getConfiguration().getNameChecker()) & NamePool.FP_MASK; } catch (XPathException err) { dynamicError("Invalid key name: " + err.getMessage(), "XTDE1260", context); } if (fprint == -1) { dynamicError("Key '" + givenkeyname + "' has not been defined", "XTDE1260", context); return null; } } // if (internal) { // System.err.println("Using key " + fprint + " on doc " + doc); // } // If the second argument is a singleton, we evaluate the function // directly; otherwise we recurse to evaluate it once for each Item // in the sequence. Expression expression = argument[1]; SequenceIterator allResults; if (Cardinality.allowsMany(expression.getCardinality())) { final XPathContext keyContext = context; final DocumentInfo document = doc; final KeyManager keyManager = controller.getKeyManager(); MappingFunction map = new MappingFunction() { // Map a value to the sequence of nodes having that value as a key value public Object map(Item item) throws XPathException { return keyManager.selectByKey( keyFingerprint, document, (AtomicValue) item, keyContext); } }; SequenceIterator keys = argument[1].iterate(context); SequenceIterator allValues = new MappingIterator(keys, map); allResults = new DocumentOrderIterator(allValues, LocalOrderComparer.getInstance()); } else { try { AtomicValue keyValue = (AtomicValue) argument[1].evaluateItem(context); if (keyValue == null) { return EmptyIterator.getInstance(); } KeyManager keyManager = controller.getKeyManager(); allResults = keyManager.selectByKey(fprint, doc, keyValue, context); } catch (XPathException e) { if (e.getLocator() == null) { e.setLocator(this); } throw e; } } if (origin == doc) { return allResults; } SubtreeFilter filter = new SubtreeFilter(); filter.origin = origin; return new ItemMappingIterator(allResults, filter); }
/** * Test whether this node test is satisfied by a given node. This alternative method is used in * the case of nodes where calculating the fingerprint is expensive, for example DOM or JDOM * nodes. * * @param node the node to be matched */ public boolean matches(NodeInfo node) { return node.getNodeKind() == kind; }
/*@NotNull*/ public Value atomize(/*@NotNull*/ NodeInfo node) { return new UntypedAtomicValue(node.getStringValueCS()); }
NodeInfoSequence(NodeInfo nodeInfo, byte axis) { this.nodeInfo = nodeInfo; this.axis = axis; iterator = nodeInfo.iterateAxis(axis); }
public String getXPath(NodeInfo node, NamespaceContext nsContext) { if (node.getNodeKind() == NodeType.DOCUMENT) return "/"; else return getPath(node, new XPathConvertor(nsContext), "/"); }
public SequenceIterator iterate(XPathContext context) throws XPathException { Controller controller = context.getController(); ObjectValue ov = (ObjectValue) controller.getParameter("{" + Test.TE_NS + "}core"); TECore core = (TECore) ov.getObject(); Expression[] argExpressions = getArguments(); String xml = "<params>\n"; List<QName> params = fe.getParams(); for (int i = 0; i < params.size(); i++) { QName param = params.get(i); xml += "<param"; xml += " local-name=\"" + param.getLocalPart() + "\""; xml += " namespace-uri=\"" + param.getNamespaceURI() + "\""; xml += " prefix=\"" + param.getPrefix() + "\""; ValueRepresentation vr = ExpressionTool.eagerEvaluate(argExpressions[i], context); // ValueRepresentation vr = // ExpressionTool.lazyEvaluate(argExpressions[i], context, 1); Value v = Value.asValue(vr); try { Node n = (Node) v.convertToJava(Node.class, context); int type = n.getNodeType(); if (type == Node.ATTRIBUTE_NODE) { xml += ">\n"; Attr attr = (Attr) n; xml += "<value " + attr.getNodeName() + "=\"" + attr.getValue().replace("&", "&") + "\""; if (attr.getPrefix() != null) { xml += " xmlns:" + attr.getPrefix() + "=\"" + attr.getNamespaceURI() + "\""; } xml += "/>\n"; // } else if (type == Node.ELEMENT_NODE || type == // Node.DOCUMENT_NODE) { // xml += ">\n"; // xml += "<value>"; // xml += DomUtils.serializeNode(n); // xml += "</value>\n"; } else if (type == Node.ELEMENT_NODE) { xml += " type=\"node()\">\n"; xml += "<value>"; xml += DomUtils.serializeNode(n); xml += "</value>\n"; } else if (type == Node.DOCUMENT_NODE) { xml += " type=\"document-node()\">\n"; xml += "<value>"; xml += DomUtils.serializeNode(n); xml += "</value>\n"; } else { ItemType it = v.getItemType(context.getConfiguration().getTypeHierarchy()); xml += " type=\"" + getTypeName(it) + "\">\n"; xml += "<value>" + n.getNodeValue() + "</value>\n"; } } catch (Exception e) { ItemType it = v.getItemType(context.getConfiguration().getTypeHierarchy()); xml += " type=\"" + getTypeName(it) + "\">\n"; xml += "<value>" + v.getStringValue() + "</value>\n"; } xml += "</param>\n"; } xml += "</params>"; // System.out.println(xml); Source src = new StreamSource(new CharArrayReader(xml.toCharArray())); // XdmValue result = null; NodeInfo result = null; try { // result = core.executeTemplate(fe, Globals.builder.build(src), // context); NodeInfo paramsNode = core.getEngine().getBuilder().build(src).getUnderlyingNode(); result = core.executeXSLFunction(context, fe, paramsNode); } catch (Exception e) { throw new RuntimeException(e); } if (result == null) { return EmptyIterator.getInstance(); } else { // Value v = Value.asValue(result); // return v.iterate(); return result.iterateAxis(Axis.CHILD); } }
/*@NotNull*/ public SequenceIterator getTypedValue(/*@NotNull*/ NodeInfo node) { return SingletonIterator.makeIterator(new UntypedAtomicValue(node.getStringValueCS())); }
private boolean shallowEquals(NodeInfo n1, Node n2) { if (n1 == n2) return true; if (n1 == null || n2 == null) return false; int type1 = n1.getNodeKind(); if (type1 == Node.CDATA_SECTION_NODE) type1 = Node.TEXT_NODE; else if (type1 == NodeType.NAMESPACE) type1 = Node.ATTRIBUTE_NODE; int type2 = n2.getNodeType(); if (type2 == Node.CDATA_SECTION_NODE) type2 = Node.TEXT_NODE; if (type1 != type2) return false; switch (type1) { case Node.PROCESSING_INSTRUCTION_NODE: ProcessingInstruction pi2 = (ProcessingInstruction) n2; String target1 = n1.getDisplayName(); String target2 = pi2.getTarget(); if (!target1.equals(target2)) return false; String data1 = n1.getStringValue(); String data2 = pi2.getData(); if (!data1.equals(data2)) return false; break; case Node.COMMENT_NODE: Comment comment2 = (Comment) n2; data1 = n1.getStringValue(); data2 = comment2.getData(); if (!data1.equals(data2)) return false; break; case Node.ELEMENT_NODE: Element element2 = (Element) n2; String namespaceURI1 = n1.getURI(); if (namespaceURI1 == null) namespaceURI1 = ""; String namespaceURI2 = element2.getNamespaceURI(); if (namespaceURI2 == null) namespaceURI2 = ""; if (!namespaceURI1.equals(namespaceURI2)) return false; String localName1 = n1.getLocalPart(); String localName2 = element2.getLocalName(); if (!localName1.equals(localName2)) return false; NodeInfoSequence attrs1 = new NodeInfoSequence(n1, Axis.ATTRIBUTE); NamedNodeMap attrs2 = element2.getAttributes(); BitSet bitSet = new BitSet(); NodeInfo attr1; while ((attr1 = attrs1.findNext()) != null) { if (isNamespaceDeclaration(attr1)) continue; namespaceURI1 = attr1.getURI(); if (namespaceURI1 == null) namespaceURI1 = ""; localName1 = attr1.getLocalPart(); String value1 = attr1.getStringValue(); int found = -1; for (int i = 0; i < attrs2.getLength(); i++) { Attr attr2 = (Attr) attrs2.item(i); namespaceURI2 = attr2.getNamespaceURI(); if (namespaceURI2 == null) namespaceURI2 = ""; localName2 = attr2.getLocalName(); if (namespaceURI1.equals(namespaceURI2) && localName1.equals(localName2)) { String value2 = attr2.getNodeValue(); if (!value1.equals(value2)) return false; found = i; break; } } if (found == -1) return false; else bitSet.set(found); } for (int i = 0; i < attrs2.getLength(); i++) { if (!bitSet.get(i)) { Attr attr2 = (Attr) attrs2.item(i); if (!DOMUtil.isNamespaceDeclaration(attr2)) return false; } } break; case Node.ATTRIBUTE_NODE: Attr attr2 = (Attr) n2; namespaceURI1 = isNamespaceDeclaration(n1) ? Namespaces.URI_XMLNS : n1.getURI(); if (namespaceURI1 == null) namespaceURI1 = ""; namespaceURI2 = attr2.getNamespaceURI(); if (namespaceURI2 == null) namespaceURI2 = ""; if (!namespaceURI1.equals(namespaceURI2)) return false; localName1 = n1.getLocalPart(); localName2 = attr2.getLocalName(); if (!localName1.equals(localName2)) return false; String value1 = n1.getStringValue(); String value2 = attr2.getNodeValue(); if (!value1.equals(value2)) return false; break; case Node.TEXT_NODE: value1 = n1.getStringValue(); value2 = n2.getNodeValue(); if (!value1.equals(value2)) return false; } return true; }
public Expression compile(Executable exec) throws XPathException { NamespaceResolver nsContext = null; int annotation = getTypeAnnotation(schemaType); // deal specially with the case where the attribute name is known statically if (attributeName instanceof StringLiteral) { String qName = Whitespace.trim(((StringLiteral) attributeName).getStringValue()); String[] parts; try { parts = getConfiguration().getNameChecker().getQNameParts(qName); } catch (QNameException e) { // This can't happen, because of previous checks return null; } if (namespace == null) { String nsuri = ""; if (!parts[0].equals("")) { nsuri = getURIForPrefix(parts[0], false); if (nsuri == null) { undeclaredNamespaceError(parts[0], "XTSE0280"); return null; } } int nameCode = getNamePool().allocate(parts[0], nsuri, parts[1]); FixedAttribute inst = new FixedAttribute(nameCode, validationAction, schemaType, annotation); inst.setContainer(this); // temporarily compileContent(exec, inst, separator); return inst; } else if (namespace instanceof StringLiteral) { String nsuri = ((StringLiteral) namespace).getStringValue(); if (nsuri.equals("")) { parts[0] = ""; } else if (parts[0].equals("")) { // Need to choose an arbitrary prefix // First see if the requested namespace is declared in the stylesheet AxisIterator iter = iterateAxis(Axis.NAMESPACE); while (true) { NodeInfo ns = (NodeInfo) iter.next(); if (ns == null) { break; } if (ns.getStringValue().equals(nsuri)) { parts[0] = ns.getLocalPart(); break; } } // Otherwise see the URI is known to the namepool if (parts[0].equals("")) { String p = getNamePool().suggestPrefixForURI(((StringLiteral) namespace).getStringValue()); if (p != null) { parts[0] = p; } } // Otherwise choose something arbitrary. This will get changed // if it clashes with another attribute if (parts[0].equals("")) { parts[0] = "ns0"; } } int nameCode = getNamePool().allocate(parts[0], nsuri, parts[1]); FixedAttribute inst = new FixedAttribute(nameCode, validationAction, schemaType, annotation); compileContent(exec, inst, separator); return inst; } } else { // if the namespace URI must be deduced at run-time from the attribute name // prefix, we need to save the namespace context of the instruction if (namespace == null) { nsContext = makeNamespaceContext(); } } ComputedAttribute inst = new ComputedAttribute( attributeName, namespace, nsContext, validationAction, schemaType, annotation, false); compileContent(exec, inst, separator); return inst; }
@Override public NodeInfo parent(NodeInfo node) { return node.getParent(); }