2 * Copyright 2005-2010 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.
16 package org.wamblee.xml;
18 import java.io.Serializable;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.List;
24 import java.util.TreeMap;
26 import junit.framework.TestCase;
28 import org.w3c.dom.Attr;
29 import org.w3c.dom.Document;
30 import org.w3c.dom.Element;
31 import org.w3c.dom.NamedNodeMap;
32 import org.w3c.dom.Node;
33 import org.w3c.dom.NodeList;
34 import org.w3c.dom.Text;
37 * XML test support utilities.
39 * @author Erik Brakkee
41 public final class XmlUtils {
43 * Disabled constructor.
51 * Checks equality of two XML documents excluding comment and processing
52 * nodes and trimming the text of the elements. In case of problems, it
53 * provides an xpath-like expression describing where the problem is.
59 public static void assertEquals(String aMsg, Document aExpected,
62 aMsg + "/" + aExpected.getDocumentElement().getLocalName(),
63 aExpected.getDocumentElement(), aActual.getDocumentElement());
66 private static <T> List<T> convertMap(NamedNodeMap aMap, Class<T> aType) {
67 List<T> result = new ArrayList<T>();
68 for (int i = 0; i < aMap.getLength(); i++) {
69 result.add((T) aMap.item(i));
74 private static List<Element> getChildElements(Element aElement) {
75 List<Element> result = new ArrayList<Element>();
76 NodeList children = aElement.getChildNodes();
77 for (int i = 0; i < children.getLength(); i++) {
78 Node node = children.item(i);
79 if (node instanceof Element) {
80 result.add((Element) node);
86 private static String getDirectText(Element aElement) {
88 NodeList children = aElement.getChildNodes();
89 for (int i = 0; i < children.getLength(); i++) {
90 Node node = children.item(i);
91 if (node instanceof Text) {
92 res += node.getTextContent() + " ";
98 private static String trim(String aText) {
99 return aText.trim().replaceAll("\\n", " ").replaceAll("\\s+", " ");
103 * Checks equality of two XML elements excluding comment and processing
104 * nodes and trimming the text of the elements (including whitespace in the middle).
105 * In case of problems, it
106 * provides an xpath-like expression describing where the problem is.
112 private static void assertEquals(String aMsg, Element aExpected,
115 TestCase.assertEquals(aMsg + "/name()", aExpected.getLocalName(),
116 aActual.getLocalName());
117 TestCase.assertEquals(aMsg + "/namespace()",
118 aExpected.getNamespaceURI(), aActual.getNamespaceURI());
121 TestCase.assertEquals(aMsg + "/text()", getDirectText(aExpected)
122 , getDirectText(aActual));
125 List<Attr> expectedAttrs = convertMap(aExpected.getAttributes(),
128 Collections.sort(expectedAttrs, new AttributeComparator());
130 List<Attr> actualAttrs = convertMap(aActual.getAttributes(), Attr.class);
131 Collections.sort(actualAttrs, new AttributeComparator());
133 TestCase.assertEquals("count(" + aMsg + "/@*)", expectedAttrs.size(),
136 for (int i = 0; i < expectedAttrs.size(); i++) {
137 String msg = aMsg + "/@" + expectedAttrs.get(i).getName();
138 assertEquals(msg, expectedAttrs.get(i), actualAttrs.get(i));
142 List<Element> expectedElems = getChildElements(aExpected);
143 List<Element> actualElems = getChildElements(aActual);
144 TestCase.assertEquals("count(" + aMsg + "/*)", expectedElems.size(),
147 // determine the how-manyth element of the given name we are at.
148 // Maps element name to the last used index (or null if not yet used)
149 Map<String, Integer> elementIndex = new TreeMap<String, Integer>();
151 for (int i = 0; i < expectedElems.size(); i++) {
152 String elemName = expectedElems.get(i).getLocalName();
153 Integer index = elementIndex.get(elemName);
161 elementIndex.put(elemName, index);
163 String msg = aMsg + "/" + expectedElems.get(i).getLocalName() + "[" +
166 assertEquals(msg, expectedElems.get(i), actualElems.get(i));
171 * Checks equality of two attributes. In case of problems, it provides an
172 * xpath-like expression describing where the problem is.
178 private static void assertEquals(String aMsg, Attr aExpected, Attr aActual) {
179 TestCase.assertEquals(aMsg + ":name", aExpected.getName(),
181 TestCase.assertEquals(aMsg + ":value", aExpected.getValue(),
186 * Comparator which compares attributes by name.
188 private static final class AttributeComparator implements Comparator<Attr>,
191 private static final long serialVersionUID = 7897287273519886301L;
196 * @see java.util.Comparator#compare(T, T)
198 public int compare(Attr aAttribute1, Attr aAttribute2) {
199 return aAttribute1.getName().compareTo(aAttribute2.getName());