La mejor manera de comparar 2 documentos XML en Java
Estoy intentando escribir una prueba automatizada de una aplicación que básicamente traduce un formato de mensaje personalizado a un mensaje XML y lo envía por el otro extremo. Tengo un buen conjunto de pares de mensajes de entrada/salida, así que todo lo que necesito hacer es enviar los mensajes de entrada y escuchar el mensaje XML que sale por el otro extremo.
Cuando llega el momento de comparar el resultado real con el resultado esperado, tengo algunos problemas. Lo primero que pensé fue simplemente hacer comparaciones de cadenas entre los mensajes esperados y reales. Esto no funciona muy bien porque los datos de ejemplo que tenemos no siempre tienen un formato coherente y, a menudo, se utilizan diferentes alias para el espacio de nombres XML (y, a veces, los espacios de nombres no se utilizan en absoluto).
Sé que puedo analizar ambas cadenas y luego recorrer cada elemento y compararlos yo mismo y esto no sería demasiado difícil de hacer, pero tengo la sensación de que hay una mejor manera o una biblioteca que podría aprovechar.
Entonces, resumida, la pregunta es:
Dadas dos cadenas de Java que contienen XML válido, ¿cómo determinaría si son semánticamente equivalentes? Puntos de bonificación si tiene una manera de determinar cuáles son las diferencias.
Suena como un trabajo para XMLUnit
- http://www.xmlunit.org/
- https://github.com/xmlunit
Ejemplo:
public class SomeTest extends XMLTestCase {
@Test
public void test() {
String xml1 = ...
String xml2 = ...
XMLUnit.setIgnoreWhitespace(true); // ignore whitespace differences
// can also compare xml Documents, InputSources, Readers, Diffs
assertXMLEqual(xml1, xml2); // assertXMLEquals comes from XMLTestCase
}
}
Lo siguiente comprobará si los documentos son iguales utilizando bibliotecas JDK estándar.
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware (verdadero); dbf.setCoalescing(verdadero); dbf.setIgnoringElementContentWhitespace(verdadero); dbf.setIgnoringComments (verdadero); DocumentBuilder db = dbf.newDocumentBuilder(); Documento doc1 = db.parse(nuevo archivo("archivo1.xml")); doc1.normalizeDocument(); Documento doc2 = db.parse(nuevo archivo("archivo2.xml")); doc2.normalizeDocument(); Assert.assertTrue(doc1.isEqualNode(doc2));
normalize() está ahí para asegurarse de que no haya ciclos (técnicamente no habría ninguno)
Sin embargo, el código anterior requerirá que los espacios en blanco sean los mismos dentro de los elementos, porque los conserva y evalúa. El analizador XML estándar que viene con Java no le permite configurar una función para proporcionar una versión canónica o comprender xml:space
si eso va a ser un problema, entonces es posible que necesite un analizador XML de reemplazo, como xerces, o usar JDOM.
Xom tiene una utilidad Canonicalizer que convierte sus DOM en un formato regular, que luego puede encadenar y comparar. Por lo tanto, independientemente de las irregularidades de los espacios en blanco o del orden de los atributos, puede obtener comparaciones periódicas y predecibles de sus documentos.
Esto funciona especialmente bien en IDE que tienen comparadores visuales de cadenas dedicados, como Eclipse. Obtiene una representación visual de las diferencias semánticas entre los documentos.