// // DOMUtil.java // /* * ome.xml.DOMUtil * *----------------------------------------------------------------------------- * * Copyright (C) 2007-2008 Open Microscopy Environment * Massachusetts Institute of Technology, * National Institutes of Health, * University of Dundee, * University of Wisconsin-Madison * * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *----------------------------------------------------------------------------- */ /*----------------------------------------------------------------------------- * * Written by: Curtis Rueden <ctrueden@wisc.edu> * *----------------------------------------------------------------------------- */ package ome.xml; import java.io.*; import java.util.Vector; import javax.xml.parsers.*; import javax.xml.transform.*; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import javax.xml.transform.dom.DOMSource; import org.w3c.dom.*; /** * DOMUtil contains useful functions for traversing and manipulating a DOM. * * <dl><dt><b>Source code:</b></dt> * <dd><a href="http://trac.openmicroscopy.org.uk/ome/browser/bioformats.git/components/ome-xml/src/ome/xml/DOMUtil.java">Trac</a>, * <a href="http://git.openmicroscopy.org/?p=bioformats.git;a=blob;f=components/ome-xml/src/ome/xml/DOMUtil.java;hb=HEAD">Gitweb</a></dd></dl> */ public final class DOMUtil { // -- Constructor -- private DOMUtil() { } // -- Static fields -- /** Factory for generating transformers. */ public static final TransformerFactory TRANS_FACT = TransformerFactory.newInstance(); /** Factory for generating document builders. */ public static final DocumentBuilderFactory DOC_FACT = DocumentBuilderFactory.newInstance(); /** Factory for generating SAX parsers. */ public static final SAXParserFactory SAX_FACT = SAXParserFactory.newInstance(); // -- I/O and XSLT methods -- /** Writes the specified DOM to the given output stream. */ public static void writeXML(OutputStream os, Document doc) throws TransformerException { Transformer idTransform = TRANS_FACT.newTransformer(); Source input = new DOMSource(doc); Result output = new StreamResult(os); idTransform.transform(input, output); } // -- Node methods -- /** Gets the local (sans namespace) name of the given node. */ public static String getName(Node node) { // NB: The node.getLocalName() method does not work. String name = node.getNodeName(); int colon = name.lastIndexOf(":"); return colon < 0 ? name : name.substring(colon + 1); } /** Gets the namespace of the given node. */ public static String getNamespace(Node node) { String name = node.getNodeName(); int colon = name.lastIndexOf(":"); return colon < 0 ? null : name.substring(0, colon); } // -- Element methods -- /** Gets the character data corresponding to the given DOM element. */ public static String getCharacterData(Element el) { Text text = getChildTextNode(el); return text == null ? null : text.getData(); } /** Sets the character data corresponding to the given DOM element. */ public static void setCharacterData(String data, Element el) { Text text = getChildTextNode(el); if (text == null) { text = el.getOwnerDocument().createTextNode(data); el.appendChild(text); } else text.setData(data); } /** * Sets the character data corresponding to the given DOM element * to the specified Object's string representation. */ public static void setCharacterData(Object data, Element el) { setCharacterData(data.toString(), el); } /** * Gets the character data corresponding to the given DOM element as * a Boolean, or null if the value is not a boolean. */ public static Boolean getBooleanCharacterData(Element el) { return stringToBoolean(getCharacterData(el)); } /** * Gets the character data corresponding to the given DOM element as * a Double, or null if the value is not a double. */ public static Double getDoubleCharacterData(Element el) { return stringToDouble(getCharacterData(el)); } /** * Gets the character data corresponding to the given DOM element as * a Float, or null if the value is not a float. */ public static Float getFloatCharacterData(Element el) { return stringToFloat(getCharacterData(el)); } /** * Gets the character data corresponding to the given DOM element as * a Integer, or null if the value is not a integer. */ public static Integer getIntegerCharacterData(Element el) { return stringToInteger(getCharacterData(el)); } /** * Gets the character data corresponding to the given DOM element as * a Long, or null if the value is not a long. */ public static Long getLongCharacterData(Element el) { return stringToLong(getCharacterData(el)); } /** * Gets the child text node containing character data * for the given DOM element. */ public static Text getChildTextNode(Element el) { if (el == null) return null; NodeList list = el.getChildNodes(); int size = list.getLength(); for (int i=0; i<size; i++) { Node node = list.item(i); if (!(node instanceof Text)) continue; return (Text) node; } return null; } /** * Gets the given element's first child DOM element with the specified name. */ public static Element getChildElement(String name, Element el) { if (name == null || el == null) return null; NodeList list = el.getChildNodes(); int size = list.getLength(); for (int i=0; i<size; i++) { Node node = list.item(i); if (!(node instanceof Element)) continue; if (name.equals(getName(node))) return (Element) node; } return null; } /** Gets a list of the given element's child DOM elements. */ public static Vector getChildElements(Element el) { return getChildElements(null, el); } /** * Gets a list of the given element's child DOM elements * with the specified name, or all child elements if name is null. */ public static Vector getChildElements(String name, Element el) { if (el == null) return null; Vector v = new Vector(); NodeList list = el.getChildNodes(); int size = list.getLength(); String cName = ":" + name; for (int i=0; i<size; i++) { Node node = list.item(i); if (!(node instanceof Element)) continue; String nodeName = node.getNodeName(); //if (name == null || name.equals(getName(node))) v.add(node); if (name == null || nodeName.equals(name) || nodeName.endsWith(cName)) { v.add(node); } } return v; } /** * Gets the given element's index-th child DOM element with the specified * name, or the index-th child element overall if name is null. */ public static Element getChildElement(String name, Element el, int index) { if (el == null) return null; NodeList list = el.getChildNodes(); int size = list.getLength(); String cName = ":" + name; int q = 0; for (int i=0; i<size; i++) { Node node = list.item(i); if (!(node instanceof Element)) continue; String nodeName = node.getNodeName(); if (name == null || nodeName.equals(name) || nodeName.endsWith(cName)) { if (q == index) return (Element) node; q++; } } return null; } /** * Gets the given element's first ancestor DOM element * with the specified name. */ public static Element getAncestorElement(String name, Element el) { if (name == null || el == null) return null; Node parent = el.getParentNode(); while (parent != null && !name.equals(getName(parent))) { parent = parent.getParentNode(); } if (parent == null || (!(parent instanceof Element))) return null; return (Element) parent; } /** Finds the first (breadth first) DOM element with the specified name. */ public static Element findElement(String name, Document doc) { return findElement(name, null, null, doc); } /** * Finds the first (breadth first) DOM element with the specified * name that has an attribute with the given name and value. */ public static Element findElement(String name, String attrName, String attrValue, Document doc) { if (name == null) return null; NodeList list = doc.getElementsByTagName(name); int size = list.getLength(); for (int i=0; i<size; i++) { Node node = list.item(i); if (!(node instanceof Element)) continue; Element el = (Element) node; if (attrName == null || attrValue == null || attrValue.equals(getAttribute(attrName, el))) { return el; } } return null; } /** * Gets a list of DOM elements with the specified name throughout * the document (not just children of a specific element). */ public static Vector findElementList(String name, Document doc) { return findElementList(name, null, null, doc); } /** * Gets a list of DOM elements with the specified name * that have an attribute with the given name and value. */ public static Vector findElementList(String name, String attrName, String attrValue, Document doc) { if (name == null) return null; Vector v = new Vector(); NodeList list = doc.getElementsByTagName(name); int size = list.getLength(); for (int i=0; i<size; i++) { Node node = list.item(i); if (!(node instanceof Element)) continue; Element el = (Element) node; if (attrName == null || attrValue == null || attrValue.equals(getAttribute(attrName, el))) { v.add(el); } } return v; } /** * Creates a child element with the given name beneath the specified element. */ public static Element createChild(Element el, String name) { return createChild(el, name, true); } /** * Creates an element with the given name in the specified element's DOM, * inserting it into the tree structure as a child of that element * if the attach flag is set. */ public static Element createChild(Element el, String name, boolean attach) { Element child = el.getOwnerDocument().createElement(name); if (attach) el.appendChild(child); return child; } // -- Attribute methods -- /** Gets a list of all attribute names for the given DOM element. */ public static String[] getAttributeNames(Element el) { NamedNodeMap map = el.getAttributes(); int len = map.getLength(); String[] attrNames = new String[len]; for (int i=0; i<len; i++) { Attr attr = (Attr) map.item(i); attrNames[i] = attr == null ? null : attr.getName(); } return attrNames; } /** Gets a list of all attribute values for the given DOM element. */ public static String[] getAttributeValues(Element el) { NamedNodeMap map = el.getAttributes(); int len = map.getLength(); String[] attrValues = new String[len]; for (int i=0; i<len; i++) { Attr attr = (Attr) map.item(i); attrValues[i] = attr == null ? null : attr.getValue(); } return attrValues; } /** * Gets the value of the given DOM element's attribute * with the specified name. */ public static String getAttribute(String name, Element el) { if (name == null || el == null) return null; if (!el.hasAttribute(name)) return null; return el.getAttribute(name); } /** * Sets the value of the given DOM element's attribute * with the specified name to the given value. */ public static void setAttribute(String name, String value, Element el) { if (name == null || value == null || el == null) return; // strip out invalid characters from the value char[] v = value.toCharArray(); int count = 0; for (int i=0; i<v.length; i++) { if (!Character.isISOControl(v[i])) count++; } if (count < v.length) { char[] nv = new char[count]; count = 0; for (int i=0; i<v.length; i++) { if (!Character.isISOControl(v[i])) nv[count++] = v[i]; } value = new String(nv); } el.setAttribute(name, value); } /** * Sets the value of the given DOM element's attribute with the * specified name to the given value's string representation. */ public static void setAttribute(String name, Object value, Element el) { setAttribute(name, value == null ? null : value.toString(), el); } /** * Gets the value of the DOM element's attribute with the given name * as a Boolean, or null if the value is not a boolean. */ public static Boolean getBooleanAttribute(String name, Element el) { return stringToBoolean(getAttribute(name, el)); } /** * Gets the value of the DOM element's attribute with the given name * as a Double, or null if the value is not a double. */ public static Double getDoubleAttribute(String name, Element el) { return stringToDouble(getAttribute(name, el)); } /** * Gets the value of the DOM element's attribute with the given name * as a Float, or null if the value is not a float. */ public static Float getFloatAttribute(String name, Element el) { return stringToFloat(getAttribute(name, el)); } /** * Gets the value of the DOM element's attribute with the given name * as an Integer, or null if the value is not an integer. */ public static Integer getIntegerAttribute(String name, Element el) { return stringToInteger(getAttribute(name, el)); } /** * Gets the value of the DOM element's attribute with the given name * as a Long, or null if the value is not a long. */ public static Long getLongAttribute(String name, Element el) { return stringToLong(getAttribute(name, el)); } // -- Helper methods -- private static Boolean stringToBoolean(String value) { if (value == null) return null; if (value.equalsIgnoreCase("true")) return Boolean.TRUE; else if (value.equalsIgnoreCase("false")) return Boolean.FALSE; else return null; } private static Double stringToDouble(String value) { if (value == null) return null; try { return new Double(value); } catch (NumberFormatException exc) { return null; } } private static Float stringToFloat(String value) { if (value == null) return null; try { return new Float(value); } catch (NumberFormatException exc) { return null; } } private static Integer stringToInteger(String value) { if (value == null) return null; try { return new Integer(value); } catch (NumberFormatException exc) { return null; } } private static Long stringToLong(String value) { if (value == null) return null; try { return new Long(value); } catch (NumberFormatException exc) { return null; } } }