1 package net.sf.mmapps.commons.util;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.OutputStream;
8 import java.io.UnsupportedEncodingException;
9 import java.util.ArrayList;
10 import java.util.List;
11
12 import javax.xml.parsers.DocumentBuilder;
13 import javax.xml.parsers.DocumentBuilderFactory;
14 import javax.xml.parsers.FactoryConfigurationError;
15 import javax.xml.parsers.ParserConfigurationException;
16
17 import org.apache.xml.serialize.OutputFormat;
18 import org.apache.xml.serialize.XMLSerializer;
19 import org.mmbase.util.logging.Logger;
20 import org.mmbase.util.logging.Logging;
21 import org.w3c.dom.Document;
22 import org.w3c.dom.DocumentFragment;
23 import org.w3c.dom.Element;
24 import org.w3c.dom.Node;
25 import org.w3c.dom.NodeList;
26 import org.w3c.dom.Text;
27
28 /***
29 * Common utilities for handling XML.
30 *
31 * @author Nico Klasens
32 */
33 public class XmlUtil {
34
35 /*** MMbase logging system */
36 private static Logger logger = Logging.getLoggerInstance(XmlUtil.class.getName());
37
38 private XmlUtil() {
39
40 }
41
42 /***
43 * Serialize <code>Document</code> instance to pretty printed
44 * <code>String</code>.
45 *
46 * @param doc Source object.
47 * @return document as <code>String</code>.
48 */
49 public static String serializeDocument(Document doc) {
50 OutputStream bos = null;
51 try {
52 bos = new ByteArrayOutputStream();
53 OutputFormat format = getXmlOutput(false, false, false, false);
54
55 XMLSerializer serializer = new XMLSerializer( bos, format );
56 serializer.serialize( doc );
57
58 return bos.toString();
59 } catch( Exception e ) {
60 logger.error( "[serializeDocument()] Pretty printing failed!" );
61 logger.debug(e);
62 } finally {
63 try {
64 if( bos != null ) bos.close();
65 }
66 catch( IOException e ) {
67 logger.error( "[serializeDocument()] Could not close OutputStream!" );
68 }
69 }
70 return "";
71 }
72
73 /***
74 * Serialize <code>DocumentFragment</code> instance to pretty printed
75 * <code>String</code>.
76 *
77 * @param docfrag Source object.
78 * @return documentfragment as <code>String</code>.
79 */
80 public static String serializeDocumentFragment(DocumentFragment docfrag) {
81 OutputStream bos = null;
82 try {
83 bos = new ByteArrayOutputStream();
84 OutputFormat format = getXmlOutput(false, false, true, true);
85
86 XMLSerializer serializer = new XMLSerializer(bos, format);
87 serializer.serialize( docfrag );
88
89 return bos.toString();
90 } catch( Exception e ) {
91 logger.error( "[serializeDocument()] Pretty printing failed!" );
92 logger.debug(e);
93 } finally {
94 try {
95 if( bos != null ) bos.close();
96 }
97 catch( IOException e ) {
98 logger.error( "[serializeDocument()] Could not close OutputStream!" );
99 }
100 }
101 return "";
102 }
103
104 /***
105 * Serialize <code>Document</code> instance to pretty printed
106 * <code>String</code>.
107 *
108 * @param element Source object.
109 * @return Element as <code>String</code>.
110 */
111 public static String serializeElement(Element element) {
112 return serializeElement(element,false);
113 }
114
115 /***
116 * Serialize <code>Document</code> instance to pretty printed
117 * <code>String</code>.
118 *
119 * @param element Source object.
120 * @param omitxml Omit the xml declaration from the returned xml
121 * @return Element as <code>String</code>.
122 */
123 public static String serializeElement(Element element, boolean omitxml) {
124 OutputStream bos = null;
125 try {
126 bos = new ByteArrayOutputStream();
127 OutputFormat format = getXmlOutput(false, false, omitxml, omitxml);
128
129 XMLSerializer serializer = new XMLSerializer(bos, format);
130 serializer.serialize( element );
131
132 return bos.toString();
133 } catch( Exception e ) {
134 logger.error( "[serializeDocument()] Pretty printing failed!" );
135 logger.debug(e);
136 } finally {
137 try {
138 if( bos != null ) bos.close();
139 }
140 catch( IOException e ) {
141 logger.error( "[serializeDocument()] Could not close OutputStream!" );
142 }
143 }
144 return "";
145 }
146
147 /***
148 * create Output format for xml
149 * Be caregull, Textnodes will be fomormatted and indented too.
150 * @param indent - indent xml
151 * @param omitComments - omit tcomments
152 * @param omitDocumentType - omit document type
153 * @param omitXMLDeclaration - omit xml declaration
154 * @return output format
155 */
156 public static OutputFormat getXmlOutput(boolean indent, boolean omitComments,
157 boolean omitDocumentType, boolean omitXMLDeclaration) {
158 OutputFormat format = new OutputFormat();
159 if (indent) {
160 format.setIndent(2);
161 format.setLineWidth(80);
162 format.setLineSeparator("\n");
163 }
164 format.setOmitComments(omitComments);
165 format.setOmitDocumentType(omitDocumentType);
166 format.setOmitXMLDeclaration(omitXMLDeclaration);
167 return format;
168 }
169
170 public static Document createDocument() {
171 try {
172 return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
173 } catch (ParserConfigurationException e) {
174 logger.debug("" + e.getMessage(), e);
175 } catch (FactoryConfigurationError e) {
176 logger.debug("" + e.getMessage(), e);
177 }
178 return null;
179 }
180
181 public static Element createChild(Element root, String elementName) {
182 return createChild(root, elementName, null);
183 }
184
185 public static Element createChild(Element root, String elementName, String namespaceURI) {
186 Element child = createElement(root.getOwnerDocument(), elementName, namespaceURI);
187 root.appendChild(child);
188 return child;
189 }
190
191 public static Element createRoot(Document doc, String elementName) {
192 return createRoot(doc, elementName, null);
193 }
194
195 public static Element createRoot(Document doc, String elementName, String namespaceURI) {
196 Element child = createElement(doc, elementName, namespaceURI);
197 doc.appendChild(child);
198 return child;
199 }
200
201 public static Element createElement(Document doc, String elementName) {
202 return createElement(doc, elementName, null);
203 }
204
205 public static Element createElement(Document doc, String elementName, String namespaceURI) {
206 Element child;
207 if (namespaceURI != null) {
208 child = doc.createElementNS(namespaceURI, elementName);
209 }
210 else {
211 child = doc.createElement(elementName);
212 }
213 return child;
214 }
215
216 public static void createAttribute(Element element, String name, String value) {
217 element.setAttribute(name, value);
218 }
219
220 public static void createText(Element root, String text) {
221 if (text != null) {
222 Text child;
223 if (text.indexOf("<")!=-1 || text.indexOf("&")!=-1 ) {
224 child = root.getOwnerDocument().createCDATASection(text);
225 } else {
226 child = root.getOwnerDocument().createTextNode(text);
227 }
228 root.appendChild(child);
229 }
230 }
231
232 public static Element createChildText(Element element, String name, String value) {
233 Element child = createChild(element, name);
234 createText(child, value);
235 return child;
236 }
237
238 public static void createAttribute(Element root, String name, boolean value) {
239 createAttribute(root, name, String.valueOf(value));
240 }
241 public static void createAttribute(Element root, String name, int value) {
242 createAttribute(root, name, String.valueOf(value));
243 }
244 public static void createAttribute(Element root, String name, float value) {
245 createAttribute(root, name, String.valueOf(value));
246 }
247 public static void createAttribute(Element root, String name, long value) {
248 createAttribute(root, name, String.valueOf(value));
249 }
250 public static void createAttribute(Element root, String name, double value) {
251 createAttribute(root, name, String.valueOf(value));
252 }
253
254 public static void createText(Element root, boolean text) {
255 createText(root, String.valueOf(text));
256 }
257 public static void createText(Element root, int text) {
258 createText(root, String.valueOf(text));
259 }
260 public static void createText(Element root, float text) {
261 createText(root, String.valueOf(text));
262 }
263 public static void createText(Element root, long text) {
264 createText(root, String.valueOf(text));
265 }
266 public static void createText(Element root, double text) {
267 createText(root, String.valueOf(text));
268 }
269
270 public static Element createChildText(Element element, String name, boolean value) {
271 return createChildText(element, name, String.valueOf(value));
272 }
273 public static Element createChildText(Element element, String name, int value) {
274 return createChildText(element, name, String.valueOf(value));
275 }
276 public static Element createChildText(Element element, String name, float value) {
277 return createChildText(element, name, String.valueOf(value));
278 }
279 public static Element createChildText(Element element, String name, long value) {
280 return createChildText(element, name, String.valueOf(value));
281 }
282 public static Element createChildText(Element element, String name, double value) {
283 return createChildText(element, name, String.valueOf(value));
284 }
285
286 public static String getText(Node node) {
287 return getText(node, "");
288 }
289
290 public static String getText(Node node, String defaultvalue) {
291 if (node == null) {
292 return defaultvalue;
293 }
294 try {
295
296 if ((node.getNodeType()==Node.TEXT_NODE)
297 || (node.getNodeType()==Node.CDATA_SECTION_NODE)
298 || (node.getNodeType()==Node.ATTRIBUTE_NODE)) {
299 return node.getNodeValue();
300 }
301
302 Node childnode=node.getFirstChild();
303 StringBuffer value = new StringBuffer();
304 while (childnode != null) {
305 if ((childnode.getNodeType()==Node.TEXT_NODE)
306 || (childnode.getNodeType()==Node.CDATA_SECTION_NODE)) {
307 value.append(childnode.getNodeValue());
308 }
309 childnode = childnode.getNextSibling();
310 }
311 if (value.length() > 0)
312 return value.toString();
313 } catch (Exception e) {
314 logger.error(e.getMessage(), e);
315 }
316 return defaultvalue;
317 }
318
319 /***
320 * Returns a W3C Document representation of the string.
321 *
322 * @param str Xml which should be converted
323 * @return DOM structure
324 */
325 public static Document toDocument(String str) {
326 Document doc = null;
327 try {
328 doc = toDocument(new ByteArrayInputStream(str.getBytes("UTF-8")));
329 } catch (UnsupportedEncodingException e) {
330 logger.error("String could not be converted to a Document.", e);
331 }
332 if (doc == null) {
333 logger.error("Erroneous String: " + str);
334 }
335 return doc;
336 }
337
338 /***
339 * Returns a W3C Document representation of the string.
340 * @param stream The input stream with the xml to convert
341 * @return DOM structure
342 */
343 public static Document toDocument(InputStream stream) {
344 try {
345 DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
346 Document doc = docBuilder.parse(stream);
347 return doc;
348 } catch (Exception e) {
349 logger.error("InputStream could not be converted to a Document.", e);
350 }
351 return null;
352 }
353
354 public static List getElements(Element element) {
355 List<Element> elements = new ArrayList<Element>();
356
357 NodeList nlist = element.getChildNodes();
358 for(int i = 0; i < nlist.getLength(); i++) {
359 Node node = nlist.item(i);
360 if (node.getNodeType() == Node.ELEMENT_NODE) {
361 Element e = (Element) node;
362 elements.add(e);
363 }
364 }
365 return elements;
366 }
367
368 public static String xmlEscape(String fragment) {
369 return fragment.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
370 }
371
372 public static String xmlUnescape(String escapedFragment) {
373 return escapedFragment.replaceAll("<", "<").replaceAll(">", ">").replaceAll("&", "&");
374 }
375
376 }