Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package de.codecentric.multitool.xml; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.List; import org.custommonkey.xmlunit.Diff; import org.custommonkey.xmlunit.XMLUnit; import org.custommonkey.xmlunit.XpathEngine; import org.custommonkey.xmlunit.exceptions.XpathException; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.XPath; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import org.dom4j.tree.DefaultAttribute; import org.dom4j.tree.DefaultElement; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Library fr die Manipulation und Auswertung von XML-Daten. * * @author markus.bonsch */ public class XmlLibrary { private static final String XML_ENCODING = "ISO-8859-15"; private static final String XPATH_SELECTOR = "xpath="; /** * Konvertiert einen XML-String in ein XML-Document * * | ${xmlDoc} = | Get Xml From String | ${xmlString} | */ public Document getXmlFromString(String xmlString) { try { Document result = null; SAXReader reader = new SAXReader(); InputSource source = new InputSource(new StringReader(xmlString)); source.setEncoding(XML_ENCODING); result = reader.read(source); if (result.getXMLEncoding() == null) result.setXMLEncoding(XML_ENCODING); return result; } catch (DocumentException e) { throw new RuntimeException("Der String " + xmlString + " kann nicht geparst werden" + e); } } /** * Konvertiert ein XML-Document in einen XML-String * * | ${xmlString} = | Get Xml From String | ${xmlDoc} | */ public String getStringFromXml(Document document) throws IOException { OutputFormat format = OutputFormat.createCompactFormat(); format.setSuppressDeclaration(true); StringWriter writer = new StringWriter(); XMLWriter xmlWriter = new XMLWriter(writer, format); xmlWriter.write(document); return writer.toString(); } /** * Liest ein XML-Document aus einer Datei ein. * * | ${xmlDoc} = | Get Xml From File | ${RESOURCES}/data/trades/template1/diamosmo-channel.xml | */ public Document getXmlFromFile(String fileName) throws DocumentException { SAXReader reader = new SAXReader(); reader.setEncoding(XML_ENCODING); return reader.read("file:" + fileName); } /** * Prueft nach, ob der angegebene Xpath Ausdurck ein Ergebnis zurueckliefert * * Beispiel: * | Xml Should Contain Element | ${xmlDoc} | //Row[@orderid="2"] | */ public void xmlShouldContainElement(Document document, String expression) { try { if (isXPathEpression(expression)) { if (!xpathExists(document, getXPath(expression))) { throw new RuntimeException("Xpath " + expression + " existiert nicht!"); } } else { throw new IllegalArgumentException("Unbekannter selector: " + expression); } } catch (Exception e) { throw new RuntimeException("Es ist ein Fehler aufgetreten: " + e, e); } } /** * Prft nach, ob der Xpath Ausdruck kein Ergebnis zurckliefert * * Beispiel: * | Xml Should Not Contain Element | ${xmlDoc} | //Row[@orderid="2"] | */ public void xmlShouldNotContainElement(Document document, String expression) { try { if (isXPathEpression(expression)) { if (xpathExists(document, getXPath(expression))) { throw new RuntimeException("Der Xpath Ausdruck: " + expression + " existiert!"); } } else { throw new IllegalArgumentException("Unbekannter selector: " + expression); } } catch (Exception e) { throw new RuntimeException("Es ist ein Fehler aufgetreten: " + e, e); } } /** * Prueft nach, ob der Xpath Ausdruck mit dem angegebenen Wert bereinstimmt. * Falls ja, wird ein Fehler gemeldet. * * Beispiel: * | Xml Should Not Match Value | ${xmlDoc} | //Row[@orderid="2"]/Column[@name="TRADE_ID"] | 07518294910871114 | */ public void xmlShouldNotMatchValue(Document document, String expression, String value) { try { org.w3c.dom.Document doc = XMLUnit.buildControlDocument(getStringFromXml(document)); if (isXPathEpression(expression)) { XpathEngine engine = XMLUnit.newXpathEngine(); String expValue = engine.evaluate(getXPath(expression), doc); if (expValue.matches(value)) { throw new RuntimeException("Der Xpath Ausdurck " + expression + " liefert eine Ergebnismenge"); } } else { throw new IllegalArgumentException("Unbekannter selector: " + expression); } } catch (Exception e) { throw new RuntimeException("Es ist ein Fehler aufgetreten: " + e, e); } } /** * Prueft nach, ob der Xpath Ausdruck mit dem angegebenen Wert bereinstimmt. * Falls nein, wird ein Fehler gemeldet. * * Beispiel: * | Xml Should Match Value | ${xmlDoc} | //Row[@orderid="2"]/Column[@name="TRADE_ID"] | 07518294910871114 | */ public void xmlShouldMatchValue(Document document, String expression, String value) { try { org.w3c.dom.Document doc = XMLUnit.buildControlDocument(getStringFromXml(document)); if (isXPathEpression(expression)) { XpathEngine simpleXpathEngine = XMLUnit.newXpathEngine(); String evaluate = simpleXpathEngine.evaluate(getXPath(expression), doc); if (!evaluate.matches(value)) { throw new RuntimeException("Der Xpath Ausdruck " + expression + " "); } } else { throw new IllegalArgumentException("Unbekannter selector: " + expression); } } catch (Exception e) { throw new RuntimeException("Es ist ein Fehler aufgetreten: " + e, e); } } /** * Ersetzt den Text-Inhalt des Xpath Elements/Attributs durch den angegeben Wert. * Wenn mehrere Elemente oder Attribute gefunden werden, wird der Wert mehrfach ersetzt. * * Beispiel: * | Replace Xml Element Value | ${xmlDoc} | //Row[@orderid="2"]/Column[@name="TRADE_ID"] | 12345 | */ public void replaceXmlElementValue(Document document, String expression, String value) { if (!isXPathEpression(expression)) { throw new IllegalArgumentException("Unbekannter selector: " + expression); } XPath path = document.createXPath(getXPath(expression)); Object result = path.evaluate(document); if (result instanceof List) { for (Object o : (List<?>) result) { if (o instanceof DefaultAttribute) { replaceAttributeValue((DefaultAttribute) o, value); } if (o instanceof DefaultElement) { replaceElementValue((DefaultElement) o, value); } } } if (result instanceof DefaultElement) { replaceElementValue((DefaultElement) result, value); } if (result instanceof DefaultAttribute) { replaceAttributeValue((DefaultAttribute) result, value); } } /** * Liefert ein Xml - Knoten als String * * Beispiel: * | ${xmlFragment} = | Get Xml Node | ${xmlDoc} | //Row[@orderid="2"] | */ public String getXmlNode(Document document, String expression) { XPath path = document.createXPath(expression); Object result = path.evaluate(document); if (result instanceof DefaultElement) { return ((DefaultElement) result).asXML(); } else { throw new RuntimeException("Der Xpath Ausdruck liefert keinen XML Knoten!"); } } /** * Vergleicht Xml1 und Xml2 inhaltlich. Die Reihenfolge von XML-Elementen muss nicht bereinstimmen. * * Beispiel: * | Xml Should Be Similar | ${expectedXml} | ${xmlString} | */ public void xmlShouldBeSimilar(String xml1, String xml2) throws SAXException, IOException { XMLUnit.setIgnoreWhitespace(true); Diff myDiff = new Diff(xml1, xml2); if (!myDiff.similar()) { throw new RuntimeException( "Abweichungen im XML: " + myDiff + "\n\nXML 1:\n" + xml1 + "\n\nXML 2:\n" + xml2); } } /** * Vergleicht die Document-Instanzen Xml1 und Xml2 inhaltlich. * Die Reihenfolge von XML-Elementen muss nicht bereinstimmen. * * Beispiel: * | Xml Should Be Similar | ${expectedXmlDoc} | ${xmlDoc} | */ public void xmlShouldBeSimilar(Document xml1, Document xml2) throws SAXException, IOException { XMLUnit.setIgnoreWhitespace(true); String stringFromXml1 = getStringFromXml(xml1); String stringFromXml2 = getStringFromXml(xml2); Diff myDiff = new Diff(stringFromXml1, stringFromXml2); if (!myDiff.similar()) { throw new RuntimeException("Abweichungen im XML: " + myDiff + "\n\nXML 1:\n" + stringFromXml1 + "\n\nXML 2:\n" + stringFromXml2); } } /** * Sortiert Elemente eines Xml-Documents. * * Der erste XPath-Ausdruck liefert die zu sortierende Elementliste, * die alle das gleiche Eltern-Element haben mssen. * Der zweite XPath-Ausdruck liefert den Wert nach dem sortiert werden soll. * * Beispiel: * | Sort Xml Nodes | ${xmlDoc} | //Row | @id | */ public void sortXmlNodes(Document document, String expression, String comparator) { if (isXPathEpression(expression) && isXPathEpression(comparator)) { List<?> nodes = document.selectNodes(getXPath(expression), getXPath(comparator)); Element parent = null; for (Object o : nodes) { if (o instanceof Element) { if (parent == null) { parent = ((Element) o).getParent(); } ((Element) o).detach(); } } parent.setContent(nodes); } else { throw new IllegalArgumentException("Unbekannter selector: " + expression); } } /** * Vergleicht Xml1 und Xml2 inhaltlich, wobei bei bereinstimmung ein Fehler geliefert wird. * Die Reihenfolge von XML-Elementen muss nicht bereinstimmen. * * Beispiel: * | Xml Should Not Be Similar | ${expectedXml} | ${xmlString} | */ public void xmlShouldNotBeSimilar(String xml1, String xml2) throws SAXException, IOException { XMLUnit.setIgnoreWhitespace(true); Diff myDiff = new Diff(xml1, xml2); if (myDiff.similar()) { throw new RuntimeException("XMLs sind gleich: " + myDiff + "\n\nXML:\n" + xml1); } } /** * Vergleicht Xml1 und Xml2 inhaltlich. Die Reihenfolge von XML-Elementen muss dabei ebenfalls bereinstimmen. * * Beispiel: * | Xml Should Be Same | ${expectedXml} | ${xmlString} | */ public void xmlShouldBeSame(String xml1, String xml2) throws SAXException, IOException { XMLUnit.setIgnoreWhitespace(true); Diff myDiff = new Diff(xml1, xml2); if (!myDiff.identical()) { throw new RuntimeException( "Abweichungen im XML: " + myDiff + "\n\nXML 1:\n" + xml1 + "\n\nXML 2:\n" + xml2); } } /** * Vergleicht die Document-Instanzen Xml1 und Xml2 inhaltlich. * Die Reihenfolge von XML-Elementen muss dabei ebenfalls bereinstimmen. * * Beispiel: * | Xml Should Be Same | ${expectedXmlDoc} | ${xmlDoc} | */ public void xmlShouldBeSame(Document xml1, Document xml2) throws SAXException, IOException { XMLUnit.setIgnoreWhitespace(true); String stringFromXml1 = getStringFromXml(xml1); String stringFromXml2 = getStringFromXml(xml2); Diff myDiff = new Diff(stringFromXml1, stringFromXml2); if (!myDiff.identical()) { throw new RuntimeException("Abweichungen im XML: " + myDiff + "\n\nXML 1:\n" + stringFromXml1 + "\n\nXML 2:\n" + stringFromXml2); } } /** * Vergleicht die Document-Instanzen Xml1 und Xml2 inhaltlich, * wobei bei bereinstimmung ein Fehler geliefert wird. * * Die Reihenfolge von XML-Elementen muss dabei ebenfalls bereinstimmen. * * Beispiel: * | Xml Should Not Be Same | ${expectedXml} | ${xmlString} | */ public void xmlShouldNotBeSame(String xml1, String xml2) throws SAXException, IOException { XMLUnit.setIgnoreWhitespace(true); Diff myDiff = new Diff(xml1, xml2); if (myDiff.identical()) { throw new RuntimeException("XMLs sind identisch: " + myDiff + "\n\nXML:\n" + xml1); } } private String getXPath(String expression) { if (expression.startsWith(XPATH_SELECTOR)) { return expression.substring(XPATH_SELECTOR.length()); } else { return expression; } } private boolean isXPathEpression(String expression) { return true; } /** * Ersetzt das Textinhalt eines Elements. * * @param element * {@link Element} * @param value * value */ private void replaceElementValue(DefaultElement element, String value) { element.setText(value); } /** * Ersetzt das Textinhalt eines Attributes * * @param attribute * {@link Attribute} * @param value * Value */ private void replaceAttributeValue(DefaultAttribute attribute, String value) { attribute.setValue(value); } private boolean xpathExists(Document document, String expression) throws IOException, SAXException, XpathException { org.w3c.dom.Document inDocument = XMLUnit.buildControlDocument(document.asXML()); XpathEngine simpleXpathEngine = XMLUnit.newXpathEngine(); NodeList nodeList = simpleXpathEngine.getMatchingNodes(expression, inDocument); int matches = nodeList.getLength(); if (matches > 0) { return true; } else { return false; } } }