2 * Copyright 2005 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.wamblee.xml;
19 import java.io.ByteArrayInputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.util.ArrayList;
25 import java.util.List;
27 import java.util.TreeMap;
29 import javax.xml.parsers.DocumentBuilder;
30 import javax.xml.parsers.DocumentBuilderFactory;
31 import javax.xml.parsers.ParserConfigurationException;
33 import org.apache.xml.serialize.OutputFormat;
34 import org.apache.xml.serialize.XMLSerializer;
35 import org.dom4j.DocumentException;
36 import org.dom4j.io.DOMReader;
37 import org.dom4j.io.DOMWriter;
38 import org.w3c.dom.Attr;
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
41 import org.w3c.dom.NamedNodeMap;
42 import org.w3c.dom.Node;
43 import org.w3c.dom.NodeList;
44 import org.xml.sax.SAXException;
47 * Some basic XML utilities for common reoccuring tasks for
50 public final class DomUtils {
53 * Disabled default constructor.
61 * Parses an XML document from a string.
62 * @param aDocument document.
65 public static Document read(String aDocument) throws SAXException, ParserConfigurationException, IOException {
66 ByteArrayInputStream is = new ByteArrayInputStream(aDocument.getBytes());
71 * Parses an XML document from a stream.
72 * @param aIs Input stream.
75 public static Document read(InputStream aIs) throws SAXException, ParserConfigurationException, IOException {
76 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
77 return builder.parse(aIs);
81 * Serializes an XML document to a stream.
82 * @param aDocument Document to serialize.
83 * @param aOs Output stream.
85 public static void serialize(Document aDocument, OutputStream aOs) throws IOException {
86 XMLSerializer serializer = new XMLSerializer(aOs, new OutputFormat());
87 serializer.serialize(aDocument);
91 * Serializes an XML document.
92 * @param aDocument Document to serialize.
93 * @return Serialized document.
95 public static String serialize(Document aDocument) throws IOException {
96 ByteArrayOutputStream os = new ByteArrayOutputStream();
97 serialize(aDocument, os);
102 * Converts a dom4j document into a w3c DOM document.
103 * @param aDocument Document to convert.
104 * @return W3C DOM document.
106 public static Document convert(org.dom4j.Document aDocument) throws DocumentException {
107 return new DOMWriter().write(aDocument);
111 * Converts a W3C DOM document into a dom4j document.
112 * @param aDocument Document to convert.
113 * @return Dom4j document.
115 public static org.dom4j.Document convert(Document aDocument) {
116 return new DOMReader().read(aDocument);
120 * Removes duplicate attributes from a DOM tree.This is useful for postprocessing the
121 * output of JTidy as a workaround for a bug in JTidy.
124 * Node to remove duplicate attributes from (recursively).
125 * Attributes of the node itself are not dealt with. Only the
126 * child nodes are dealt with.
128 public static void removeDuplicateAttributes(Node aNode) {
129 NodeList list = aNode.getChildNodes();
130 for (int i = 0; i < list.getLength(); i++) {
131 Node node = list.item(i);
132 if (node instanceof Element) {
133 removeDuplicateAttributes((Element) node);
134 removeDuplicateAttributes(node);
140 * Removes duplicate attributes from an element.
145 private static void removeDuplicateAttributes(Element aElement) {
146 NamedNodeMap attributes = aElement.getAttributes();
147 Map<String, Attr> uniqueAttributes = new TreeMap<String, Attr>();
148 List<Attr> attlist = new ArrayList<Attr>();
149 for (int i = 0; i < attributes.getLength(); i++) {
150 Attr attribute = (Attr) attributes.item(i);
151 if (uniqueAttributes.containsKey(attribute.getNodeName())) {
152 System.out.println("Detected duplicate attribute '"
153 + attribute.getNodeName() + "'");
155 uniqueAttributes.put(attribute.getNodeName(), attribute);
156 attlist.add(attribute);
158 // Remove all attributes from the element.
159 for (Attr att : attlist) {
160 aElement.removeAttributeNode(att);
162 // Add the unique attributes back to the element.
163 for (Attr att : uniqueAttributes.values()) {
164 aElement.setAttributeNode(att);