@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; } }
@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; }
@Override public String convert(NodeInfo source) { switch (source.getNodeKind()) { case NodeType.ATTRIBUTE: case NodeType.NAMESPACE: return delegate.convert(source); } return super.convert(source); }
public String getXPath(NodeInfo node, NamespaceContext nsContext) { if (node.getNodeKind() == NodeType.DOCUMENT) return "/"; else return getPath(node, new XPathConvertor(nsContext), "/"); }
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; }
/** * 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; }
/** 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); }