001 package ezvcard.util;
002
003 import java.io.IOException;
004 import java.io.Reader;
005 import java.io.StringReader;
006 import java.io.StringWriter;
007 import java.io.Writer;
008 import java.util.ArrayList;
009 import java.util.HashMap;
010 import java.util.List;
011 import java.util.Map;
012
013 import javax.xml.parsers.DocumentBuilder;
014 import javax.xml.parsers.DocumentBuilderFactory;
015 import javax.xml.parsers.ParserConfigurationException;
016 import javax.xml.transform.Transformer;
017 import javax.xml.transform.TransformerConfigurationException;
018 import javax.xml.transform.TransformerException;
019 import javax.xml.transform.TransformerFactory;
020 import javax.xml.transform.TransformerFactoryConfigurationError;
021 import javax.xml.transform.dom.DOMSource;
022 import javax.xml.transform.stream.StreamResult;
023
024 import org.w3c.dom.Document;
025 import org.w3c.dom.Element;
026 import org.w3c.dom.Node;
027 import org.w3c.dom.NodeList;
028 import org.xml.sax.InputSource;
029 import org.xml.sax.SAXException;
030
031 /*
032 Copyright (c) 2013, Michael Angstadt
033 All rights reserved.
034
035 Redistribution and use in source and binary forms, with or without
036 modification, are permitted provided that the following conditions are met:
037
038 1. Redistributions of source code must retain the above copyright notice, this
039 list of conditions and the following disclaimer.
040 2. Redistributions in binary form must reproduce the above copyright notice,
041 this list of conditions and the following disclaimer in the documentation
042 and/or other materials provided with the distribution.
043
044 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
045 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
046 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
047 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
048 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
049 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
050 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
051 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
052 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
053 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
054
055 The views and conclusions contained in the software and documentation are those
056 of the authors and should not be interpreted as representing official policies,
057 either expressed or implied, of the FreeBSD Project.
058 */
059
060 /**
061 * Generic XML utility methods.
062 * @author Michael Angstadt
063 */
064 public class XmlUtils {
065 /**
066 * Creates a new XML document.
067 * @return the XML document
068 */
069 public static Document createDocument() {
070 try {
071 DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
072 fact.setNamespaceAware(true);
073 DocumentBuilder db = fact.newDocumentBuilder();
074 return db.newDocument();
075 } catch (ParserConfigurationException e) {
076 //no complex configurations
077 }
078 return null;
079 }
080
081 /**
082 * Parses an XML string into a DOM.
083 * @param xml the XML string
084 * @return the parsed DOM
085 * @throws SAXException if the string is not valid XML
086 */
087 public static Document toDocument(String xml) throws SAXException {
088 try {
089 return toDocument(new StringReader(xml));
090 } catch (IOException e) {
091 //reading from string
092 }
093 return null;
094 }
095
096 /**
097 * Parses an XML document from a reader.
098 * @param reader the reader
099 * @return the parsed DOM
100 * @throws SAXException if the XML is not valid
101 * @throws IOException if there is a problem reading from the reader
102 */
103 public static Document toDocument(Reader reader) throws SAXException, IOException {
104 try {
105 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
106 dbf.setNamespaceAware(true);
107 dbf.setIgnoringComments(true);
108 DocumentBuilder db = dbf.newDocumentBuilder();
109 return db.parse(new InputSource(reader));
110 } catch (ParserConfigurationException e) {
111 //never thrown because we're not doing anything fancy with the configuration
112 }
113 return null;
114 }
115
116 /**
117 * Converts an XML node to a string.
118 * @param node the XML node
119 * @return the string
120 */
121 public static String toString(Node node) {
122 return toString(node, new HashMap<String, String>());
123 }
124
125 /**
126 * Converts an XML node to a string.
127 * @param node the XML node
128 * @param outputProperties the output properties
129 * @return the string
130 */
131 public static String toString(Node node, Map<String, String> outputProperties) {
132 try {
133 StringWriter writer = new StringWriter();
134 toWriter(node, writer, outputProperties);
135 return writer.toString();
136 } catch (TransformerException e) {
137 //writing to string
138 }
139 return null;
140 }
141
142 /**
143 * Writes an XML node to a writer.
144 * @param node the XML node
145 * @param writer the writer
146 * @throws TransformerException if there's a problem writing to the writer
147 */
148 public static void toWriter(Node node, Writer writer) throws TransformerException {
149 toWriter(node, writer, new HashMap<String, String>());
150 }
151
152 /**
153 * Writes an XML node to a writer.
154 * @param node the XML node
155 * @param writer the writer
156 * @param outputProperties the output properties
157 * @throws TransformerException if there's a problem writing to the writer
158 */
159 public static void toWriter(Node node, Writer writer, Map<String, String> outputProperties) throws TransformerException {
160 try {
161 Transformer transformer = TransformerFactory.newInstance().newTransformer();
162 for (Map.Entry<String, String> property : outputProperties.entrySet()) {
163 try {
164 transformer.setOutputProperty(property.getKey(), property.getValue());
165 } catch (IllegalArgumentException e) {
166 //ignore invalid output properties
167 }
168 }
169
170 DOMSource source = new DOMSource(node);
171 StreamResult result = new StreamResult(writer);
172 transformer.transform(source, result);
173 } catch (TransformerConfigurationException e) {
174 //no complex configurations
175 } catch (TransformerFactoryConfigurationError e) {
176 //no complex configurations
177 }
178 }
179
180 /**
181 * Gets all the elements out of a {@link NodeList}.
182 * @param nodeList the node list
183 * @return the elements
184 */
185 public static List<Element> toElementList(NodeList nodeList) {
186 List<Element> elements = new ArrayList<Element>();
187 for (int i = 0; i < nodeList.getLength(); i++) {
188 Node node = nodeList.item(i);
189 if (node instanceof Element) {
190 elements.add((Element) node);
191 }
192 }
193 return elements;
194 }
195
196 /**
197 * Gets the root element of a document.
198 * @param parent the document
199 * @return the root element
200 */
201 public static Element getRootElement(Document parent) {
202 return getFirstChildElement((Node) parent);
203 }
204
205 /**
206 * Gets the first child element of an element.
207 * @param parent the parent element
208 * @return the first child element or null if there are no child elements
209 */
210 public static Element getFirstChildElement(Element parent) {
211 return getFirstChildElement((Node) parent);
212 }
213
214 /**
215 * Gets the first child element of a node.
216 * @param parent the node
217 * @return the first child element or null if there are no child elements
218 */
219 private static Element getFirstChildElement(Node parent) {
220 NodeList nodeList = parent.getChildNodes();
221 for (int i = 0; i < nodeList.getLength(); i++) {
222 Node node = nodeList.item(i);
223 if (node instanceof Element) {
224 return (Element) node;
225 }
226 }
227 return null;
228 }
229
230 private XmlUtils() {
231 //hide
232 }
233 }