La mejor manera de comparar 2 documentos XML en Java

Resuelto Mike Deck asked hace 16 años • 15 respuestas

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.

Mike Deck avatar Sep 27 '08 04:09 Mike Deck
Aceptado

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
  }
}
Tom avatar Sep 26 '2008 21:09 Tom

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:spacesi eso va a ser un problema, entonces es posible que necesite un analizador XML de reemplazo, como xerces, o usar JDOM.

Archimedes Trajano avatar Nov 18 '2010 02:11 Archimedes Trajano

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.

skaffman avatar Sep 26 '2008 21:09 skaffman