Java tutorial
// // Copyright 2007 Requea. // ------------------------------------------------------------------------ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.util.Stack; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.Source; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.CDATASection; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; /** * Utilities to manipulate w3c DOM trees. * @author Pierre Dubois */ public class XMLUtils { private static DocumentBuilderFactory fDocumentFactory; private static Stack fParsersPool = new Stack(); /** * Public Id and the Resource path (of the cached copy) * of the DTDs for tag library descriptors. */ public static final String TAGLIB_DTD_PUBLIC_ID_11 = "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"; public static final String TAGLIB_DTD_RESOURCE_PATH_11 = "/javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd"; public static final String TAGLIB_DTD_PUBLIC_ID_12 = "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"; public static final String TAGLIB_DTD_RESOURCE_PATH_12 = "/javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd"; /** * Public Id and the Resource path (of the cached copy) * of the DTDs for web application deployment descriptors */ public static final String WEBAPP_DTD_PUBLIC_ID_22 = "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"; public static final String WEBAPP_DTD_RESOURCE_PATH_22 = "/javax/servlet/resources/web-app_2_2.dtd"; public static final String WEBAPP_DTD_PUBLIC_ID_23 = "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"; public static final String WEBAPP_DTD_RESOURCE_PATH_23 = "/javax/servlet/resources/web-app_2_3.dtd"; /** * List of the Public IDs that we cache, and their * associated location. This is used by * an EntityResolver to return the location of the * cached copy of a DTD. */ public static final String[] CACHED_DTD_PUBLIC_IDS = { TAGLIB_DTD_PUBLIC_ID_11, TAGLIB_DTD_PUBLIC_ID_12, WEBAPP_DTD_PUBLIC_ID_22, WEBAPP_DTD_PUBLIC_ID_23, }; public static final String[] CACHED_DTD_RESOURCE_PATHS = { TAGLIB_DTD_RESOURCE_PATH_11, TAGLIB_DTD_RESOURCE_PATH_12, WEBAPP_DTD_RESOURCE_PATH_22, WEBAPP_DTD_RESOURCE_PATH_23, }; private static synchronized void initFactory() { if (fDocumentFactory != null) return; fDocumentFactory = DocumentBuilderFactory.newInstance(); fDocumentFactory.setNamespaceAware(true); fDocumentFactory.setIgnoringElementContentWhitespace(true); fDocumentFactory.setValidating(false); } public static synchronized DocumentBuilder getParser() throws ParserConfigurationException { if (fParsersPool.isEmpty()) { // create a new parser initFactory(); DocumentBuilder builder = fDocumentFactory.newDocumentBuilder(); builder.setEntityResolver(entityResolver); return builder; } else { return (DocumentBuilder) fParsersPool.pop(); } } public static synchronized void releaseParser(DocumentBuilder parser) { if (parser != null) fParsersPool.push(parser); } /** * Parse an xml document as an imput stream. * @param is * @return * @throws XMLException */ public static Document parse(InputStream is) { DocumentBuilder builder = null; try { builder = getParser(); // parse the document Document doc = builder.parse(is); return doc; } catch (Exception e) { } finally { releaseParser(builder); } } /** * Parses an xml document as a string. * @param xml * @return * @throws XMLException */ public static Document parse(String xml) { DocumentBuilder builder = null; try { builder = getParser(); // parse the document try { InputStream is = new ByteArrayInputStream(xml.getBytes()); Document doc = builder.parse(is); return doc; } catch (SAXException e) { } catch (IOException e) { } } catch (ParserConfigurationException e) { } finally { releaseParser(builder); } } /** * Creates a new and empty document. * @return */ public static Document newDocument() { DocumentBuilder builder = null; try { builder = getParser(); return builder.newDocument(); } catch (ParserConfigurationException e) { throw new RuntimeException(e); } finally { releaseParser(builder); } } /** * Creates a new document with a document root element. * @param name * @return */ public static Element newElement(String name) { DocumentBuilder builder = null; try { builder = getParser(); Document doc = builder.newDocument(); Element el = doc.createElement(name); doc.appendChild(el); return el; } catch (ParserConfigurationException e) { throw new RuntimeException(e); } finally { releaseParser(builder); } } /** * Serialize an element to a string. * @param element * @return * @throws XMLException */ public static String ElementToString(Element element) { return privateElementToString(element, true, true); } public static String ElementToString(Element element, boolean pretty) { return privateElementToString(element, true, pretty); } /** * Serialize a document to a string * @param doc * @return */ public static String DocumentToString(Document doc) { return privateElementToString(doc.getDocumentElement(), false, true); } public static String DocumentToString(Document doc, boolean pretty) { return privateElementToString(doc.getDocumentElement(), false, pretty); } /** * Get the first child element to match a given name. * Look for a child element in the same namespace as the parent. * * @param parent * @param name * @return */ public static Element getChild(Element parent, String name) { Element child = getFirstChild(parent); while (child != null) { String tagName = child.getTagName(); if (tagName != null && tagName.equals(name)) { return child; } if (child.getPrefix() != null && child.getPrefix().equals(parent.getPrefix()) && child.getLocalName() != null && child.getLocalName().equals(name)) { return child; } child = getNext(child); } return child; } /** * Get the first child element to match a given name. * Look for a child element in the same namespace as the parent. * * @param parent * @param name * @return */ public static Element getChild(Element parent, String ns, String name) { Element child = getFirstChild(parent); while (child != null) { if (child.getLocalName().equals(name)) { if (ns == null && child.getNamespaceURI() == null) { return child; } else if (ns != null && ns.equals(child.getNamespaceURI())) { return child; } } child = getNext(child); } return child; } /** * Get the first child element of an element. * @param el * @return */ public static Element getFirstChild(Element el) { if (el == null) { return null; } NodeList lst = el.getChildNodes(); int len = lst.getLength(); for (int i = 0; i < len; i++) { Node n = lst.item(i); if (n instanceof Element) return (Element) n; } return null; } /** * Get the next sibling element of a given element. * @param el * @return */ public static Element getNext(Element el) { Node n = el.getNextSibling(); while (n != null && !(n instanceof Element)) { // get the next one n = n.getNextSibling(); } if (n instanceof Element) { return (Element) n; } // else, nothing to return return null; } /** * Get the next sibling element of a given element. * @param el * @return */ public static Element getNextSibling(Element el) { String tagName = el.getTagName(); if (tagName == null) { return null; } Node n = el.getNextSibling(); while (n != null && (!(n instanceof Element) || !tagName.equals(((Element) n).getTagName()))) { // get the next one n = n.getNextSibling(); } if (n instanceof Element) { return (Element) n; } else { // else, nothing to return return null; } } /** * Get the previous sibling element of a given element. * @param el * @return */ public static Element getPrevious(Element el) { Node n = el.getPreviousSibling(); while (n != null && !(n instanceof Element)) { // get the next one n = n.getPreviousSibling(); } if (n instanceof Element) { return (Element) n; } else { // else, nothing to return return null; } } /** * Get the previous sibling element of a given element. * @param el * @return */ public static Element getPreviousSibling(Element el) { Node n = el.getPreviousSibling(); while (n != null && (!(n instanceof Element) || !el.getTagName().equals(((Element) n).getTagName()))) { // get the next one n = n.getPreviousSibling(); } if (n instanceof Element) { return (Element) n; } else { // else, nothing to return return null; } } /** * Returns the text value of an element. * @param el * @return */ public static String getTextValue(Element el) { StringBuffer b = new StringBuffer(); // retrieve the text node child NodeList nl = el.getChildNodes(); int len = nl.getLength(); for (int i = 0; i < len; i++) { Node n = nl.item(i); if (n instanceof Text) { Text t = (Text) n; b.append(t.getData()); } } // trim the result, ignoring the first spaces and cariage return int iFirst = 0; for (; iFirst < b.length(); iFirst++) { char c = b.charAt(iFirst); if (c != ' ' && c != '\r' && c != '\n' && c != '\t') { break; } } // start by the end as well int iLast = b.length() - 1; for (; iLast >= 0; iLast--) { char c = b.charAt(iLast); if (c != ' ' && c != '\r' && c != '\n' && c != '\t') { break; } } return b.substring(iFirst, iLast + 1); } /** * Get the text value of a child element with a given name. * @param parent * @param name * @return */ public static String getChildText(Element parent, String name) { Element child = getChild(parent, name); if (child != null) { return getTextValue(child); } return null; } /** * Get the text value of a child element with a given name. * @param parent * @param name * @return */ public static String getChildText(Element parent, String ns, String name) { Element child = getChild(parent, ns, name); if (child != null) { return getTextValue(child); } return null; } /** * Adds an element as a child of a given element. * The child is created with the same namespace as the parent. * @param parent * @param name * @return */ public static Element addElement(Element parent, String name) { Document doc = parent.getOwnerDocument(); String qname; if (parent.getPrefix() != null) { qname = parent.getPrefix() + ":" + name; } else { qname = name; } Element child = doc.createElementNS(parent.getNamespaceURI(), qname); parent.appendChild(child); return child; } /** * Adds an element as a child of a given element and sets the text value. * The child is created with the same namespace as the parent. * * @param parent * @param name * @param textValue * @return */ public static Element addElement(Element parent, String name, String textValue) { Element child = addElement(parent, name); // create a text node if (textValue == null) { textValue = ""; } Text txt = child.getOwnerDocument().createTextNode(textValue); child.appendChild(txt); return child; } /** * Sets the text value for a given element. * @param el * @param value */ public static void setText(Element el, String value) { // remove the children if already exist while (el.getFirstChild() != null) { el.removeChild(el.getFirstChild()); } if (value == null) { value = ""; } Text txt = el.getOwnerDocument().createTextNode(value); el.appendChild(txt); } /** * Sets the text value for a given element as a CDATA section * @param el * @param value */ public static void setCDATA(Element el, String value) { // remove the children if already exist while (el.getFirstChild() != null) { el.removeChild(el.getFirstChild()); } if (value == null) { value = ""; } CDATASection txt = el.getOwnerDocument().createCDATASection(value); el.appendChild(txt); } /** * Retrieve the namespace for a given prefix. * Does a lookup into the parent hierarchy. * @param el * @param prefix * @return */ public static String getNamespace(Element el, String prefix) { Element parent = el; while (parent != null) { String ns = parent.getAttribute("xmlns:" + prefix); if (ns != null && ns.length() > 0) { return ns; } // get the parent Node n = parent.getParentNode(); if (n instanceof Element) { parent = (Element) n; } else { parent = null; } } // nothing found return null; } /* * serialize an element to a string. */ private static String privateElementToString(Element element, boolean omitXMLDecl, boolean pretty) { try { Source source = new DOMSource(element); StringWriter out = new StringWriter(); StreamResult result = new StreamResult(out); Transformer xformer = TransformerFactory.newInstance().newTransformer(); xformer.setOutputProperty("indent", "yes"); xformer.transform(source, result); return out.toString(); } catch (Exception e) { } } public static String getAttribute(Element el, String att) { String str = el.getAttribute(att); if (str == null || str.length() == 0) { return null; } else { return str; } } static EntityResolver entityResolver = new MyEntityResolver(); static private class MyEntityResolver implements EntityResolver { public InputSource resolveEntity(String publicId, String systemId) throws SAXException { for (int i = 0; i < CACHED_DTD_PUBLIC_IDS.length; i++) { String cachedDtdPublicId = CACHED_DTD_PUBLIC_IDS[i]; if (cachedDtdPublicId.equals(publicId)) { String resourcePath = CACHED_DTD_RESOURCE_PATHS[i]; InputStream input = this.getClass().getResourceAsStream(resourcePath); if (input == null) { throw new SAXException("file.not.found" + resourcePath); } InputSource isrc = new InputSource(input); return isrc; } } return null; } } }