📄 xmlnode.java
字号:
} private Namespace getDefaultNamespace() { String prefix = ""; String uri = (dom.lookupNamespaceURI(null) == null) ? "" : dom.lookupNamespaceURI(null); return Namespace.create(prefix, uri); } private String getExistingPrefixFor(Namespace namespace) { if (getDefaultNamespace().getUri().equals(namespace.getUri())) { return ""; } return dom.lookupPrefix(namespace.getUri()); } private Namespace getNodeNamespace() { String uri = dom.getNamespaceURI(); String prefix = dom.getPrefix(); if (uri == null) uri = ""; if (prefix == null) prefix = ""; return Namespace.create(prefix, uri); } Namespace getNamespace() { return getNodeNamespace(); } void removeNamespace(Namespace namespace) { Namespace current = getNodeNamespace(); // Do not remove in-use namespace if (namespace.is(current)) return; NamedNodeMap attrs = this.dom.getAttributes(); for (int i=0; i<attrs.getLength(); i++) { XmlNode attr = XmlNode.createImpl(attrs.item(i)); if (namespace.is(attr.getNodeNamespace())) return; } // TODO I must confess I am not sure I understand the spec fully. See ECMA357 13.4.4.31 String existingPrefix = getExistingPrefixFor(namespace); if (existingPrefix != null) { if (namespace.isUnspecifiedPrefix()) { // we should remove any namespace with this URI from scope; we do this by declaring a namespace with the same // prefix as the existing prefix and setting its URI to the default namespace declareNamespace(existingPrefix, getDefaultNamespace().getUri()); } else { if (existingPrefix.equals(namespace.getPrefix())) { declareNamespace(existingPrefix, getDefaultNamespace().getUri()); } } } else { // the argument namespace is not declared in this scope, so do nothing. } } private void setProcessingInstructionName(String localName) { org.w3c.dom.ProcessingInstruction pi = (ProcessingInstruction)this.dom; // We cannot set the node name; Document.renameNode() only supports elements and attributes. So we replace it pi.getParentNode().replaceChild( pi, pi.getOwnerDocument().createProcessingInstruction(localName, pi.getData()) ); } final void setLocalName(String localName) { if (dom instanceof ProcessingInstruction) { setProcessingInstructionName(localName); } else { String prefix = dom.getPrefix(); if (prefix == null) prefix = ""; this.dom = dom.getOwnerDocument().renameNode(dom, dom.getNamespaceURI(), QName.qualify(prefix, localName)); } } final QName getQname() { String uri = (dom.getNamespaceURI()) == null ? "" : dom.getNamespaceURI(); String prefix = (dom.getPrefix() == null) ? "" : dom.getPrefix(); return QName.create( uri, dom.getLocalName(), prefix ); } void addMatchingChildren(XMLList result, XmlNode.Filter filter) { Node node = this.dom; NodeList children = node.getChildNodes(); for(int i=0; i<children.getLength(); i++) { Node childnode = children.item(i); XmlNode child = XmlNode.createImpl(childnode); if (filter.accept(childnode)) { result.addToList(child); } } } XmlNode[] getMatchingChildren(Filter filter) { ArrayList rv = new ArrayList(); NodeList nodes = this.dom.getChildNodes(); for (int i=0; i<nodes.getLength(); i++) { Node node = nodes.item(i); if (filter.accept(node)) { rv.add( createImpl(node) ); } } return (XmlNode[])rv.toArray(new XmlNode[0]); } XmlNode[] getAttributes() { NamedNodeMap attrs = this.dom.getAttributes(); // TODO Or could make callers handle null? if (attrs == null) throw new IllegalStateException("Must be element."); XmlNode[] rv = new XmlNode[attrs.getLength()]; for (int i=0; i<attrs.getLength(); i++) { rv[i] = createImpl( attrs.item(i) ); } return rv; } String getAttributeValue() { return ((Attr)dom).getValue(); } void setAttribute(QName name, String value) { if (!(dom instanceof Element)) throw new IllegalStateException("Can only set attribute on elements."); name.setAttribute( (Element)dom, value ); } void replaceWith(XmlNode other) { Node replacement = other.dom; if (replacement.getOwnerDocument() != this.dom.getOwnerDocument()) { replacement = this.dom.getOwnerDocument().importNode(replacement, true); } this.dom.getParentNode().replaceChild(replacement, this.dom); } String ecmaToXMLString(XmlProcessor processor) { if (this.isElementType()) { Element copy = (Element)this.dom.cloneNode(true); Namespace[] inScope = this.getInScopeNamespaces(); for (int i=0; i<inScope.length; i++) { declareNamespace(copy, inScope[i].getPrefix(), inScope[i].getUri()); } return processor.ecmaToXmlString(copy); } else { return processor.ecmaToXmlString(dom); } } static class Namespace { static Namespace create(String prefix, String uri) { if (prefix == null) throw new IllegalArgumentException("Empty string represents default namespace prefix"); if (uri == null) throw new IllegalArgumentException("Namespace may not lack a URI"); Namespace rv = new Namespace(); rv.prefix = prefix; rv.uri = uri; return rv; } static Namespace create(String uri) { Namespace rv = new Namespace(); rv.uri = uri; return rv; } static final Namespace GLOBAL = create("", ""); private String prefix; private String uri; private Namespace() { } public String toString() { if (prefix == null) return "XmlNode.Namespace [" + uri + "]"; return "XmlNode.Namespace [" + prefix + "{" + uri + "}]"; } boolean isUnspecifiedPrefix() { return prefix == null; } boolean is(Namespace other) { return this.prefix != null && other.prefix != null && this.prefix.equals(other.prefix) && this.uri.equals(other.uri); } boolean isEmpty() { return prefix != null && prefix.equals("") && uri.equals(""); } boolean isDefault() { return prefix != null && prefix.equals(""); } boolean isGlobal() { return uri != null && uri.equals(""); } // Called by QName // TODO Move functionality from QName lookupPrefix to here private void setPrefix(String prefix) { if (prefix == null) throw new IllegalArgumentException(); this.prefix = prefix; } String getPrefix() { return prefix; } String getUri() { return uri; } } // TODO Where is this class used? No longer using it in QName implementation static class QName { static QName create(Namespace namespace, String localName) { // A null namespace indicates a wild-card match for any namespace // A null localName indicates "*" from the point of view of ECMA357 if (localName != null && localName.equals("*")) throw new RuntimeException("* is not valid localName"); QName rv = new QName(); rv.namespace = namespace; rv.localName = localName; return rv; } /** @deprecated */ static QName create(String uri, String localName, String prefix) { return create(Namespace.create(prefix, uri), localName); } static String qualify(String prefix, String localName) { if (prefix == null) throw new IllegalArgumentException("prefix must not be null"); if (prefix.length() > 0) return prefix + ":" + localName; return localName; } private Namespace namespace; private String localName; private QName() { } public String toString() { return "XmlNode.QName [" + localName + "," + namespace + "]"; } private boolean equals(String one, String two) { if (one == null && two == null) return true; if (one == null || two == null) return false; return one.equals(two); } private boolean namespacesEqual(Namespace one, Namespace two) { if (one == null && two == null) return true; if (one == null || two == null) return false; return equals(one.getUri(), two.getUri()); } final boolean isEqualTo(QName other) { if (!namespacesEqual(this.namespace, other.namespace)) return false; if (!equals(this.localName, other.localName)) return false; return true; } void lookupPrefix(org.w3c.dom.Node node) { if (node == null) throw new IllegalArgumentException("node must not be null"); String prefix = node.lookupPrefix(namespace.getUri()); if (prefix == null) { // check to see if we match the default namespace String defaultNamespace = node.lookupNamespaceURI(null); if (defaultNamespace == null) defaultNamespace = ""; String nodeNamespace = namespace.getUri(); if (nodeNamespace.equals(defaultNamespace)) { prefix = ""; } } int i = 0; while(prefix == null) { String generatedPrefix = "e4x_" + i++; String generatedUri = node.lookupNamespaceURI(generatedPrefix); if (generatedUri == null) { prefix = generatedPrefix; org.w3c.dom.Node top = node; while(top.getParentNode() != null && top.getParentNode() instanceof org.w3c.dom.Element) { top = top.getParentNode(); } ((org.w3c.dom.Element)top).setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" + prefix, namespace.getUri()); } } namespace.setPrefix(prefix); } String qualify(org.w3c.dom.Node node) { if (namespace.getPrefix() == null) { if (node != null) { lookupPrefix(node); } else { if (namespace.getUri().equals("")) { namespace.setPrefix(""); } else { // TODO I am not sure this is right, but if we are creating a standalone node, I think we can set the // default namespace on the node itself and not worry about setting a prefix for that namespace. namespace.setPrefix(""); } } } return qualify(namespace.getPrefix(), localName); } void setAttribute(org.w3c.dom.Element element, String value) { if (namespace.getPrefix() == null) lookupPrefix(element); element.setAttributeNS(namespace.getUri(), qualify(namespace.getPrefix(), localName), value); } /** @deprecated Use getNamespace() */ String getUri() { return namespace.getUri(); } /** @deprecated Use getNamespace() */ String getPrefix() { return namespace.getPrefix(); } Namespace getNamespace() { return namespace; } String getLocalName() { return localName; } } static class List { private java.util.Vector v; List() { v = new java.util.Vector(); } private void _add(XmlNode n) { v.add(n); } XmlNode item(int index) { return (XmlNode)(v.get(index)); } void remove(int index) { v.remove(index); } void add(List other) { for (int i=0; i<other.length(); i++) { _add(other.item(i)); } } void add(List from, int startInclusive, int endExclusive) { for (int i=startInclusive; i<endExclusive; i++) { _add(from.item(i)); } } void add(XmlNode node) { _add(node); } /** @deprecated */ void add(XML xml) { _add(xml.getAnnotation()); } /** @deprecated */ void addToList(Object toAdd) { if (toAdd instanceof Undefined) { // Missing argument do nothing... return; } if (toAdd instanceof XMLList) { XMLList xmlSrc = (XMLList)toAdd; for (int i = 0; i < xmlSrc.length(); i++) { this._add((xmlSrc.item(i)).getAnnotation()); } } else if (toAdd instanceof XML) { this._add(((XML)(toAdd)).getAnnotation()); } else if (toAdd instanceof XmlNode) { this._add((XmlNode)toAdd); } } int length() { return v.size(); } } static abstract class Filter { static final Filter COMMENT = new Filter() { boolean accept(Node node) { return node.getNodeType() == Node.COMMENT_NODE; } }; static final Filter TEXT = new Filter() { boolean accept(Node node) { return node.getNodeType() == Node.TEXT_NODE; } }; static Filter PROCESSING_INSTRUCTION(final XMLName name) { return new Filter() { boolean accept(Node node) { if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) { ProcessingInstruction pi = (ProcessingInstruction)node; return name.matchesLocalName(pi.getTarget()); } return false; } }; } static Filter ELEMENT = new Filter() { boolean accept(Node node) { return node.getNodeType() == Node.ELEMENT_NODE; } }; static Filter TRUE = new Filter() { boolean accept(Node node) { return true; } }; abstract boolean accept(Node node); } // Support experimental Java interface org.w3c.dom.Node toDomNode() { return this.dom; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -