| /* |
| * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package stream.XMLStreamWriterTest; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Iterator; |
| |
| import javax.xml.XMLConstants; |
| import javax.xml.namespace.NamespaceContext; |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.FactoryConfigurationError; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.stream.XMLStreamException; |
| import javax.xml.stream.XMLStreamWriter; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.SAXException; |
| |
| public class DOMUtil { |
| |
| private static DocumentBuilder db; |
| |
| private static String fixNull(String s) { |
| if (s == null) |
| return ""; |
| else |
| return s; |
| } |
| |
| /** |
| * Creates a new DOM document. |
| */ |
| public static Document createDom() { |
| synchronized (DOMUtil.class) { |
| if (db == null) { |
| try { |
| DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); |
| dbf.setNamespaceAware(true); |
| db = dbf.newDocumentBuilder(); |
| } catch (ParserConfigurationException e) { |
| throw new FactoryConfigurationError(e); |
| } |
| } |
| return db.newDocument(); |
| } |
| } |
| |
| public static Node createDOMNode(InputStream inputStream) { |
| |
| DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); |
| dbf.setNamespaceAware(true); |
| dbf.setValidating(false); |
| try { |
| DocumentBuilder builder = dbf.newDocumentBuilder(); |
| try { |
| return builder.parse(inputStream); |
| } catch (SAXException e) { |
| e.printStackTrace(); // To change body of catch statement use |
| // File | Settings | File Templates. |
| } catch (IOException e) { |
| e.printStackTrace(); // To change body of catch statement use |
| // File | Settings | File Templates. |
| } |
| } catch (ParserConfigurationException pce) { |
| IllegalArgumentException iae = new IllegalArgumentException(pce.getMessage()); |
| iae.initCause(pce); |
| throw iae; |
| } |
| return null; |
| } |
| |
| public static void serializeNode(Element node, XMLStreamWriter writer) throws XMLStreamException { |
| String nodePrefix = fixNull(node.getPrefix()); |
| String nodeNS = fixNull(node.getNamespaceURI()); |
| |
| // See if nodePrefix:nodeNS is declared in writer's NamespaceContext |
| // before writing start element |
| // Writing start element puts nodeNS in NamespaceContext even though |
| // namespace declaration not written |
| boolean prefixDecl = isPrefixDeclared(writer, nodeNS, nodePrefix); |
| |
| writer.writeStartElement(nodePrefix, node.getLocalName(), nodeNS); |
| |
| if (node.hasAttributes()) { |
| NamedNodeMap attrs = node.getAttributes(); |
| int numOfAttributes = attrs.getLength(); |
| // write namespace declarations first. |
| // if we interleave this with attribue writing, |
| // Zephyr will try to fix it and we end up getting inconsistent |
| // namespace bindings. |
| for (int i = 0; i < numOfAttributes; i++) { |
| Node attr = attrs.item(i); |
| String nsUri = fixNull(attr.getNamespaceURI()); |
| if (nsUri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { |
| // handle default ns declarations |
| String local = attr.getLocalName().equals(XMLConstants.XMLNS_ATTRIBUTE) ? "" : attr.getLocalName(); |
| if (local.equals(nodePrefix) && attr.getNodeValue().equals(nodeNS)) { |
| prefixDecl = true; |
| } |
| // this is a namespace declaration, not an attribute |
| writer.setPrefix(attr.getLocalName(), attr.getNodeValue()); |
| writer.writeNamespace(attr.getLocalName(), attr.getNodeValue()); |
| } |
| } |
| } |
| // node's namespace is not declared as attribute, but declared on |
| // ancestor |
| if (!prefixDecl) { |
| writer.writeNamespace(nodePrefix, nodeNS); |
| } |
| |
| // Write all other attributes which are not namespace decl. |
| if (node.hasAttributes()) { |
| NamedNodeMap attrs = node.getAttributes(); |
| int numOfAttributes = attrs.getLength(); |
| |
| for (int i = 0; i < numOfAttributes; i++) { |
| Node attr = attrs.item(i); |
| String attrPrefix = fixNull(attr.getPrefix()); |
| String attrNS = fixNull(attr.getNamespaceURI()); |
| if (!attrNS.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { |
| String localName = attr.getLocalName(); |
| if (localName == null) { |
| // TODO: this is really a bug in the caller for not |
| // creating proper DOM tree. |
| // will remove this workaround after plugfest |
| localName = attr.getNodeName(); |
| } |
| boolean attrPrefixDecl = isPrefixDeclared(writer, attrNS, attrPrefix); |
| if (!attrPrefix.equals("") && !attrPrefixDecl) { |
| // attr has namespace but namespace decl is there in |
| // ancestor node |
| // So write the namespace decl before writing the attr |
| writer.setPrefix(attr.getLocalName(), attr.getNodeValue()); |
| writer.writeNamespace(attrPrefix, attrNS); |
| } |
| writer.writeAttribute(attrPrefix, attrNS, localName, attr.getNodeValue()); |
| } |
| } |
| } |
| |
| if (node.hasChildNodes()) { |
| NodeList children = node.getChildNodes(); |
| for (int i = 0; i < children.getLength(); i++) { |
| Node child = children.item(i); |
| switch (child.getNodeType()) { |
| case Node.PROCESSING_INSTRUCTION_NODE: |
| writer.writeProcessingInstruction(child.getNodeValue()); |
| case Node.DOCUMENT_TYPE_NODE: |
| break; |
| case Node.CDATA_SECTION_NODE: |
| writer.writeCData(child.getNodeValue()); |
| break; |
| case Node.COMMENT_NODE: |
| writer.writeComment(child.getNodeValue()); |
| break; |
| case Node.TEXT_NODE: |
| writer.writeCharacters(child.getNodeValue()); |
| break; |
| case Node.ELEMENT_NODE: |
| serializeNode((Element) child, writer); |
| break; |
| } |
| } |
| } |
| writer.writeEndElement(); |
| } |
| |
| private static boolean isPrefixDeclared(XMLStreamWriter writer, String nsUri, String prefix) { |
| boolean prefixDecl = false; |
| NamespaceContext nscontext = writer.getNamespaceContext(); |
| Iterator prefixItr = nscontext.getPrefixes(nsUri); |
| while (prefixItr.hasNext()) { |
| if (prefix.equals(prefixItr.next())) { |
| prefixDecl = true; |
| break; |
| } |
| } |
| return prefixDecl; |
| } |
| |
| /** |
| * Gets the first child of the given name, or null. |
| */ |
| public static Element getFirstChild(Element e, String nsUri, String local) { |
| for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) { |
| if (n.getNodeType() == Node.ELEMENT_NODE) { |
| Element c = (Element) n; |
| if (c.getLocalName().equals(local) && c.getNamespaceURI().equals(nsUri)) |
| return c; |
| } |
| } |
| return null; |
| } |
| |
| } |