java - ¿Cómo ignoro ciertos elementos cuando comparo XML?
junit xmlunit (5)
Tengo un mensaje XML como ese:
<root>
<elementA>something</elementA>
<elementB>something else</elementB>
<elementC>yet another thing</elementC>
</root>
Quiero comparar un mensaje de este tipo producido por un método bajo prueba con un mensaje esperado, pero no me importa el elemento elementA
Entonces, me gustaría que el mensaje anterior se considere igual a:
<root>
<elementA>something different</elementA>
<elementB>something else</elementB>
<elementC>yet another thing</elementC>
</root>
Estoy usando la última versión de XMLUnit .
Me estoy imaginando que la respuesta implica crear un DifferenceListener
personalizado; Simplemente no quiero reinventar la rueda si hay algo listo para usar.
Sugerencias que utilizan una biblioteca que no sea XMLUnit son bienvenidas.
Ahora puede probar ${xmlunit.ignore}
en XMLUnit 2.6.0 (agregue la dependencia xmlunit-placeholders). El código de muestra es el siguiente.
Diff diff = DiffBuilder
.compare(expectedXML)
.withTest(actualXML)
.withDifferenceEvaluator(new PlaceholderDifferenceEvaluator())
.build();
XML esperado:
<root>
<elementA>${xmlunit.ignore}</elementA>
<elementB>something else</elementB>
<elementC>yet another thing</elementC>
</root>
XML real:
<root>
<elementA>anything</elementA>
<elementB>something else</elementB>
<elementC>yet another thing</elementC>
</root>
Observe que actualmente $ {xmlunit.ignore} solo es compatible con el nodo de texto y el valor de atributo ignorancia, como se puede ver en las pruebas unitarias .
Las cosas han cambiado mucho para XMLUnit desde que se respondió esta pregunta.
Ahora puede ignorar fácilmente un nodo cuando usa un DiffBuilder
:
final Diff documentDiff = DiffBuilder
.compare(expectedSource)
.withTest(actualSource)
.withNodeFilter(node -> !node.getNodeName().equals(someName))
.build();
Si luego llama a documentDiff.hasDifferences()
nodos añadidos al filtro serán ignorados.
Terminé implementando un DifferenceListener
que toma una lista de nombres de nodo (con espacios de nombres) para ignorar las diferencias de texto para:
public class IgnoreNamedElementsDifferenceListener implements DifferenceListener {
private Set<String> blackList = new HashSet<String>();
public IgnoreNamedElementsDifferenceListener(String ... elementNames) {
for (String name : elementNames) {
blackList.add(name);
}
}
public int differenceFound(Difference difference) {
if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
if (blackList.contains(difference.getControlNodeDetail().getNode().getParentNode().getNodeName())) {
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
}
public void skippedComparison(Node node, Node node1) {
}
}
Utilizaría XSLT y la transformación de identidad para filtrar los elementos que deseo ignorar y comparar los resultados.
Ver XSL: cómo copiar un árbol, pero quitando algunos nodos? antes en SO.
public class IgnoreNamedElementsDifferenceListener implements DifferenceListener {
private Set<String> blackList = new HashSet<String>();
public IgnoreNamedElementsDifferenceListener(String ... elementNames) {
for (String name : elementNames) {
blackList.add(name);
}
}
public int differenceFound(Difference difference) {
if (difference.getId() == DifferenceConstants.TEXT_VALUE_ID) {
if (blackList.contains(difference.getControlNodeDetail().getNode().getParentNode().getNodeName())) {
return DifferenceListener.RETURN_IGNORE_DIFFERENCE_NODES_IDENTICAL;
}
}
return DifferenceListener.RETURN_ACCEPT_DIFFERENCE;
}
public void skippedComparison(Node node, Node node1) {
}
}
Cómo invocar esta implementación a mi método para ver las diferencias después de ignorar el nodo específico para la comparación.