Melhor maneira de comparar 2 documentos XML em Java

198

Estou tentando escrever um teste automatizado de um aplicativo que basicamente converte um formato de mensagem personalizado em uma mensagem XML e o envia para o outro lado. Eu tenho um bom conjunto de pares de mensagens de entrada / saída, então tudo o que preciso fazer é enviar as mensagens de entrada e ouvir a mensagem XML sair do outro lado.

Quando chega a hora de comparar a saída real com a saída esperada, estou com alguns problemas. Meu primeiro pensamento foi apenas fazer comparações de string nas mensagens esperadas e reais. Isso não funciona muito bem porque os dados de exemplo que temos nem sempre são formatados de maneira consistente e, muitas vezes, aliases diferentes são usados ​​para o espaço para nome XML (e às vezes os espaços para nome não são usados).

Eu sei que posso analisar as duas strings e, em seguida, percorrer cada elemento e compará-las pessoalmente, e isso não seria muito difícil de fazer, mas sinto que há uma maneira melhor ou uma biblioteca que eu poderia aproveitar.

Então, resumida, a questão é:

Dadas duas Java Strings que contêm XML válido, como você determinaria se elas são semanticamente equivalentes? Pontos de bônus se você tiver uma maneira de determinar quais são as diferenças.

Mike Deck
fonte

Respostas:

197

Soa como um trabalho para XMLUnit

Exemplo:

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
fonte
1
Eu já tive problemas com o XMLUNit no passado, ele tem sido muito conturbado com as versões da API XML e não se mostrou confiável. Já faz um tempo desde que eu o abandonei no XOM, então talvez seja um problema desde então.
22468 skaffman
63
Para iniciantes no XMLUnit, observe que, por padrão, myDiff.similar () retornará false se os documentos de controle e teste diferirem em indentação / novas linhas. Eu esperava esse comportamento do myDiff.identical () e não do myDiff.similar (). Inclua XMLUnit.setIgnoreWhitespace (true); no seu método setUp para alterar o comportamento de todos os testes em sua classe de teste ou use-o em um método de teste individual para alterar o comportamento apenas desse teste.
007
1
@Stew, obrigado pelo seu comentário, apenas começando com XMLUnit e tenho certeza que teria enfrentado esse problema. 1
Jay Jay
2
Caso você esteja tentando fazer isso com o XMLUnit 2 no github, a versão 2 é uma reescrita completa; portanto, este exemplo é para XMLUnit 1 no SourceForge. Além disso, a página do sourceforge indica "O XMLUnit para Java 1.x ainda será mantido".
Yngvar Kristiansen
1
O método é assertXMLEqual a partir de XMLAssert.java .
precisa saber é o seguinte
36

A seguir, será verificado se os documentos são iguais usando as bibliotecas JDK padrão.

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance ();
dbf.setNamespaceAware (true);
dbf.setCoalescing (true);
dbf.setIgnoringElementContentWhitespace (true);
dbf.setIgnoringComments (true);
DocumentBuilder db = dbf.newDocumentBuilder ();

Documento doc1 = db.parse (novo arquivo ("arquivo1.xml"));
doc1.normalizeDocument ();

Documento doc2 = db.parse (novo arquivo ("arquivo2.xml"));
doc2.normalizeDocument ();

Assert.assertTrue (doc1.isEqualNode (doc2));

normalize () existe para garantir que não haja ciclos (tecnicamente não haveria)

O código acima exigirá que os espaços em branco sejam os mesmos nos elementos, porque ele os preserva e avalia. O analisador XML padrão que acompanha o Java não permite que você configure um recurso para fornecer uma versão canônica ou entenda xml:spacese isso será um problema; pode ser necessário um analisador XML de substituição, como xerces ou usar JDOM.

Archimedes Trajano
fonte
4
Isso funciona perfeitamente para XMLs sem espaços para nome ou com prefixos de espaço para nome "normalizados". Eu duvido que ele funciona se um XML é <ns1: um xmlns: ns1 = "ns" /> eo outro é <NS2: um xmlns: ns2 = "ns" />
koppor
dbf.setIgnoringElementContentWhitespace (true) não tem o resultado Eu esperaria que o <root> nome </root> não seja igual ao <root> nome </name> com esta solução (preenchida com dois espaços), mas XMLUnit fornece o mesmo resultado neste caso (JDK8)
Miklos Krivan
Para mim, isso não ignora quebras de linha, o que é um problema.
Flyout91
setIgnoringElementContentWhitespace(false)
Archimedes Trajano
28

O Xom possui um utilitário Canonicalizer que transforma seus DOMs em um formulário regular, que você pode, então, modificar e comparar. Portanto, independentemente das irregularidades em espaço em branco ou da ordem dos atributos, você pode obter comparações regulares e previsíveis de seus documentos.

Isso funciona especialmente bem em IDEs que possuem comparadores visuais de String dedicados, como o Eclipse. Você obtém uma representação visual das diferenças semânticas entre os documentos.

skaffman
fonte
21

A versão mais recente do XMLUnit pode ajudar o trabalho de afirmar que dois XML são iguais. Também XMLUnit.setIgnoreWhitespace()e XMLUnit.setIgnoreAttributeOrder()pode ser necessário para o caso em questão.

Veja o código de trabalho de um exemplo simples de uso da Unidade XML abaixo.

import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.XMLUnit;
import org.junit.Assert;

public class TestXml {

    public static void main(String[] args) throws Exception {
        String result = "<abc             attr=\"value1\"                title=\"something\">            </abc>";
        // will be ok
        assertXMLEquals("<abc attr=\"value1\" title=\"something\"></abc>", result);
    }

    public static void assertXMLEquals(String expectedXML, String actualXML) throws Exception {
        XMLUnit.setIgnoreWhitespace(true);
        XMLUnit.setIgnoreAttributeOrder(true);

        DetailedDiff diff = new DetailedDiff(XMLUnit.compareXML(expectedXML, actualXML));

        List<?> allDifferences = diff.getAllDifferences();
        Assert.assertEquals("Differences found: "+ diff.toString(), 0, allDifferences.size());
    }

}

Se estiver usando o Maven, adicione-o ao seu pom.xml:

<dependency>
    <groupId>xmlunit</groupId>
    <artifactId>xmlunit</artifactId>
    <version>1.4</version>
</dependency>
acdcjunior
fonte
Isso é perfeito para pessoas que precisam comparar a partir de um método estático.
Andy B
Esta é a resposta perfeita. Obrigado .. No entanto, eu preciso ignorar os nós que não existem. Como eu não quero ver no resultado uma saída desse tipo: Presença esperada do nó filho "null", mas foi ...... Como posso fazer isso? Saudações. @acdcjunior
limonik
1
XMLUnit.setIgnoreAttributeOrder (true); não funciona. Se alguns nós tiverem uma ordem diferente, a comparação falhará.
Bevor
[UPDATE] esta solução funciona: stackoverflow.com/questions/33695041/…
Bevor
Você percebe que "IgnoreAttributeOrder" significa ignorar a ordem dos atributos e não ignorar a ordem dos nós, certo?
Acdcjunior 22/05
7

Obrigado, eu estendi isso, tente isso ...

import java.io.ByteArrayInputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

public class XmlDiff 
{
    private boolean nodeTypeDiff = true;
    private boolean nodeValueDiff = true;

    public boolean diff( String xml1, String xml2, List<String> diffs ) throws Exception
    {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        dbf.setCoalescing(true);
        dbf.setIgnoringElementContentWhitespace(true);
        dbf.setIgnoringComments(true);
        DocumentBuilder db = dbf.newDocumentBuilder();


        Document doc1 = db.parse(new ByteArrayInputStream(xml1.getBytes()));
        Document doc2 = db.parse(new ByteArrayInputStream(xml2.getBytes()));

        doc1.normalizeDocument();
        doc2.normalizeDocument();

        return diff( doc1, doc2, diffs );

    }

    /**
     * Diff 2 nodes and put the diffs in the list 
     */
    public boolean diff( Node node1, Node node2, List<String> diffs ) throws Exception
    {
        if( diffNodeExists( node1, node2, diffs ) )
        {
            return true;
        }

        if( nodeTypeDiff )
        {
            diffNodeType(node1, node2, diffs );
        }

        if( nodeValueDiff )
        {
            diffNodeValue(node1, node2, diffs );
        }


        System.out.println(node1.getNodeName() + "/" + node2.getNodeName());

        diffAttributes( node1, node2, diffs );
        diffNodes( node1, node2, diffs );

        return diffs.size() > 0;
    }

    /**
     * Diff the nodes
     */
    public boolean diffNodes( Node node1, Node node2, List<String> diffs ) throws Exception
    {
        //Sort by Name
        Map<String,Node> children1 = new LinkedHashMap<String,Node>();      
        for( Node child1 = node1.getFirstChild(); child1 != null; child1 = child1.getNextSibling() )
        {
            children1.put( child1.getNodeName(), child1 );
        }

        //Sort by Name
        Map<String,Node> children2 = new LinkedHashMap<String,Node>();      
        for( Node child2 = node2.getFirstChild(); child2!= null; child2 = child2.getNextSibling() )
        {
            children2.put( child2.getNodeName(), child2 );
        }

        //Diff all the children1
        for( Node child1 : children1.values() )
        {
            Node child2 = children2.remove( child1.getNodeName() );
            diff( child1, child2, diffs );
        }

        //Diff all the children2 left over
        for( Node child2 : children2.values() )
        {
            Node child1 = children1.get( child2.getNodeName() );
            diff( child1, child2, diffs );
        }

        return diffs.size() > 0;
    }


    /**
     * Diff the nodes
     */
    public boolean diffAttributes( Node node1, Node node2, List<String> diffs ) throws Exception
    {        
        //Sort by Name
        NamedNodeMap nodeMap1 = node1.getAttributes();
        Map<String,Node> attributes1 = new LinkedHashMap<String,Node>();        
        for( int index = 0; nodeMap1 != null && index < nodeMap1.getLength(); index++ )
        {
            attributes1.put( nodeMap1.item(index).getNodeName(), nodeMap1.item(index) );
        }

        //Sort by Name
        NamedNodeMap nodeMap2 = node2.getAttributes();
        Map<String,Node> attributes2 = new LinkedHashMap<String,Node>();        
        for( int index = 0; nodeMap2 != null && index < nodeMap2.getLength(); index++ )
        {
            attributes2.put( nodeMap2.item(index).getNodeName(), nodeMap2.item(index) );

        }

        //Diff all the attributes1
        for( Node attribute1 : attributes1.values() )
        {
            Node attribute2 = attributes2.remove( attribute1.getNodeName() );
            diff( attribute1, attribute2, diffs );
        }

        //Diff all the attributes2 left over
        for( Node attribute2 : attributes2.values() )
        {
            Node attribute1 = attributes1.get( attribute2.getNodeName() );
            diff( attribute1, attribute2, diffs );
        }

        return diffs.size() > 0;
    }
    /**
     * Check that the nodes exist
     */
    public boolean diffNodeExists( Node node1, Node node2, List<String> diffs ) throws Exception
    {
        if( node1 == null && node2 == null )
        {
            diffs.add( getPath(node2) + ":node " + node1 + "!=" + node2 + "\n" );
            return true;
        }

        if( node1 == null && node2 != null )
        {
            diffs.add( getPath(node2) + ":node " + node1 + "!=" + node2.getNodeName() );
            return true;
        }

        if( node1 != null && node2 == null )
        {
            diffs.add( getPath(node1) + ":node " + node1.getNodeName() + "!=" + node2 );
            return true;
        }

        return false;
    }

    /**
     * Diff the Node Type
     */
    public boolean diffNodeType( Node node1, Node node2, List<String> diffs ) throws Exception
    {       
        if( node1.getNodeType() != node2.getNodeType() ) 
        {
            diffs.add( getPath(node1) + ":type " + node1.getNodeType() + "!=" + node2.getNodeType() );
            return true;
        }

        return false;
    }

    /**
     * Diff the Node Value
     */
    public boolean diffNodeValue( Node node1, Node node2, List<String> diffs ) throws Exception
    {       
        if( node1.getNodeValue() == null && node2.getNodeValue() == null )
        {
            return false;
        }

        if( node1.getNodeValue() == null && node2.getNodeValue() != null )
        {
            diffs.add( getPath(node1) + ":type " + node1 + "!=" + node2.getNodeValue() );
            return true;
        }

        if( node1.getNodeValue() != null && node2.getNodeValue() == null )
        {
            diffs.add( getPath(node1) + ":type " + node1.getNodeValue() + "!=" + node2 );
            return true;
        }

        if( !node1.getNodeValue().equals( node2.getNodeValue() ) )
        {
            diffs.add( getPath(node1) + ":type " + node1.getNodeValue() + "!=" + node2.getNodeValue() );
            return true;
        }

        return false;
    }


    /**
     * Get the node path
     */
    public String getPath( Node node )
    {
        StringBuilder path = new StringBuilder();

        do
        {           
            path.insert(0, node.getNodeName() );
            path.insert( 0, "/" );
        }
        while( ( node = node.getParentNode() ) != null );

        return path.toString();
    }
}
Dardo
fonte
3
Tarde demais, mas só queria observar que esse trecho de código tem um erro: em diffNodes (), o node2 não é mencionado - o segundo loop reutiliza o node1 incorretamente (editei o código para corrigir isso). Além disso, possui 1 limitação: devido ao modo como os mapas filho são codificados, esse diff não suporta o caso em que os nomes dos elementos não são exclusivos, ou seja, elementos contendo elementos filhos repetíveis.
usar o seguinte
7

Com base na resposta de Tom , aqui está um exemplo usando o XMLUnit v2.

Ele usa essas dependências automatizadas

    <dependency>
        <groupId>org.xmlunit</groupId>
        <artifactId>xmlunit-core</artifactId>
        <version>2.0.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.xmlunit</groupId>
        <artifactId>xmlunit-matchers</artifactId>
        <version>2.0.0</version>
        <scope>test</scope>
    </dependency>

..e aqui está o código de teste

import static org.junit.Assert.assertThat;
import static org.xmlunit.matchers.CompareMatcher.isIdenticalTo;
import org.xmlunit.builder.Input;
import org.xmlunit.input.WhitespaceStrippedSource;

public class SomeTest extends XMLTestCase {
    @Test
    public void test() {
        String result = "<root></root>";
        String expected = "<root>  </root>";

        // ignore whitespace differences
        // https://github.com/xmlunit/user-guide/wiki/Providing-Input-to-XMLUnit#whitespacestrippedsource
        assertThat(result, isIdenticalTo(new WhitespaceStrippedSource(Input.from(expected).build())));

        assertThat(result, isIdenticalTo(Input.from(expected).build())); // will fail due to whitespace differences
    }
}

A documentação que descreve isso é https://github.com/xmlunit/xmlunit#comparing-two-documents

Tom Saleeba
fonte
3

skaffman parece estar dando uma boa resposta.

outra maneira é provavelmente formatar o XML usando um utilitário de linha de comando como xmlstarlet ( http://xmlstar.sourceforge.net/ ) e, em seguida, formatar as duas strings e usar qualquer utilitário diff (biblioteca) para diferenciar os arquivos de saída resultantes. Não sei se essa é uma boa solução quando há problemas com namespaces.

anjanb
fonte
3

O AssertJ 1.4+ possui asserções específicas para comparar o conteúdo XML:

String expectedXml = "<foo />";
String actualXml = "<bar />";
assertThat(actualXml).isXmlEqualTo(expectedXml);

Aqui está a documentação

Gian Marco Gherardi
fonte
2

Estou usando o Altova DiffDog, que tem opções para comparar arquivos XML estruturalmente (ignorando dados de string).

Isso significa que (se estiver marcando a opção 'ignorar texto'):

<foo a="xxx" b="xxx">xxx</foo>

e

<foo b="yyy" a="yyy">yyy</foo> 

são iguais no sentido de que têm igualdade estrutural. Isso é útil se você tiver arquivos de exemplo que diferem nos dados, mas não na estrutura!

Pimin Konstantin Kefaloukos
fonte
3
Apenas menos é que não é gratuito (99 € para uma licença profissional), com 30 dias de teste.
Pimin Konstantin Kefaloukos 26/10/10
2
Encontrei apenas o utilitário ( altova.com/diffdog/diff-merge-tool.html ); bom ter uma biblioteca.
dma_k
1

Isso irá comparar XMLs de cadeia completa (reformatando-os no caminho). Isso facilita o trabalho com seu IDE (IntelliJ, Eclipse), pois você apenas clica e vê visualmente a diferença nos arquivos XML.

import org.apache.xml.security.c14n.CanonicalizationException;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.c14n.InvalidCanonicalizerException;
import org.w3c.dom.Element;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.IOException;
import java.io.StringReader;

import static org.apache.xml.security.Init.init;
import static org.junit.Assert.assertEquals;

public class XmlUtils {
    static {
        init();
    }

    public static String toCanonicalXml(String xml) throws InvalidCanonicalizerException, ParserConfigurationException, SAXException, CanonicalizationException, IOException {
        Canonicalizer canon = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS);
        byte canonXmlBytes[] = canon.canonicalize(xml.getBytes());
        return new String(canonXmlBytes);
    }

    public static String prettyFormat(String input) throws TransformerException, ParserConfigurationException, IOException, SAXException, InstantiationException, IllegalAccessException, ClassNotFoundException {
        InputSource src = new InputSource(new StringReader(input));
        Element document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(src).getDocumentElement();
        Boolean keepDeclaration = input.startsWith("<?xml");
        DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
        DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
        LSSerializer writer = impl.createLSSerializer();
        writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
        writer.getDomConfig().setParameter("xml-declaration", keepDeclaration);
        return writer.writeToString(document);
    }

    public static void assertXMLEqual(String expected, String actual) throws ParserConfigurationException, IOException, SAXException, CanonicalizationException, InvalidCanonicalizerException, TransformerException, IllegalAccessException, ClassNotFoundException, InstantiationException {
        String canonicalExpected = prettyFormat(toCanonicalXml(expected));
        String canonicalActual = prettyFormat(toCanonicalXml(actual));
        assertEquals(canonicalExpected, canonicalActual);
    }
}

Eu prefiro isso ao XmlUnit porque o código do cliente (código de teste) é mais limpo.

Wojtek
fonte
1
Isso funciona bem em dois testes que fiz agora, com o mesmo XML e com XML diferente. Com o IntelliJ diff, as diferenças no XML comparado são fáceis de identificar.
Yngvar Kristiansen
1
A propósito, você precisará dessa dependência se usar o Maven: <dependency> <groupId> org.apache.santuario </groupId> <artifactId> xmlsec </artifactId> <versão> 2.0.6 </version> </ dependência>
Yngvar Kristiansen
1

O código abaixo funciona para mim

String xml1 = ...
String xml2 = ...
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreAttributeOrder(true);
XMLAssert.assertXMLEqual(actualxml, xmlInDb);
arunkumar sambu
fonte
1
Algum contexto? Referência da biblioteca?
Ben
0

Usando JExamXML com aplicativo java

    import com.a7soft.examxml.ExamXML;
    import com.a7soft.examxml.Options;

       .................

       // Reads two XML files into two strings
       String s1 = readFile("orders1.xml");
       String s2 = readFile("orders.xml");

       // Loads options saved in a property file
       Options.loadOptions("options");

       // Compares two Strings representing XML entities
       System.out.println( ExamXML.compareXMLString( s1, s2 ) );
sreehari
fonte
0

Eu exigi a mesma funcionalidade solicitada na pergunta principal. Como eu não tinha permissão para usar nenhuma biblioteca de terceiros, criei minha própria solução com base na solução @Archimedes Trajano.

A seguir está a minha solução.

import java.io.ByteArrayInputStream;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.junit.Assert;
import org.w3c.dom.Document;

/**
 * Asserts for asserting XML strings.
 */
public final class AssertXml {

    private AssertXml() {
    }

    private static Pattern NAMESPACE_PATTERN = Pattern.compile("xmlns:(ns\\d+)=\"(.*?)\"");

    /**
     * Asserts that two XML are of identical content (namespace aliases are ignored).
     * 
     * @param expectedXml expected XML
     * @param actualXml actual XML
     * @throws Exception thrown if XML parsing fails
     */
    public static void assertEqualXmls(String expectedXml, String actualXml) throws Exception {
        // Find all namespace mappings
        Map<String, String> fullnamespace2newAlias = new HashMap<String, String>();
        generateNewAliasesForNamespacesFromXml(expectedXml, fullnamespace2newAlias);
        generateNewAliasesForNamespacesFromXml(actualXml, fullnamespace2newAlias);

        for (Entry<String, String> entry : fullnamespace2newAlias.entrySet()) {
            String newAlias = entry.getValue();
            String namespace = entry.getKey();
            Pattern nsReplacePattern = Pattern.compile("xmlns:(ns\\d+)=\"" + namespace + "\"");
            expectedXml = transletaNamespaceAliasesToNewAlias(expectedXml, newAlias, nsReplacePattern);
            actualXml = transletaNamespaceAliasesToNewAlias(actualXml, newAlias, nsReplacePattern);
        }

        // nomralize namespaces accoring to given mapping

        DocumentBuilder db = initDocumentParserFactory();

        Document expectedDocuemnt = db.parse(new ByteArrayInputStream(expectedXml.getBytes(Charset.forName("UTF-8"))));
        expectedDocuemnt.normalizeDocument();

        Document actualDocument = db.parse(new ByteArrayInputStream(actualXml.getBytes(Charset.forName("UTF-8"))));
        actualDocument.normalizeDocument();

        if (!expectedDocuemnt.isEqualNode(actualDocument)) {
            Assert.assertEquals(expectedXml, actualXml); //just to better visualize the diffeences i.e. in eclipse
        }
    }


    private static DocumentBuilder initDocumentParserFactory() throws ParserConfigurationException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(false);
        dbf.setCoalescing(true);
        dbf.setIgnoringElementContentWhitespace(true);
        dbf.setIgnoringComments(true);
        DocumentBuilder db = dbf.newDocumentBuilder();
        return db;
    }

    private static String transletaNamespaceAliasesToNewAlias(String xml, String newAlias, Pattern namespacePattern) {
        Matcher nsMatcherExp = namespacePattern.matcher(xml);
        if (nsMatcherExp.find()) {
            xml = xml.replaceAll(nsMatcherExp.group(1) + "[:]", newAlias + ":");
            xml = xml.replaceAll(nsMatcherExp.group(1) + "=", newAlias + "=");
        }
        return xml;
    }

    private static void generateNewAliasesForNamespacesFromXml(String xml, Map<String, String> fullnamespace2newAlias) {
        Matcher nsMatcher = NAMESPACE_PATTERN.matcher(xml);
        while (nsMatcher.find()) {
            if (!fullnamespace2newAlias.containsKey(nsMatcher.group(2))) {
                fullnamespace2newAlias.put(nsMatcher.group(2), "nsTr" + (fullnamespace2newAlias.size() + 1));
            }
        }
    }

}

Ele compara duas cadeias XML e cuida de qualquer mapeamento de espaço de nome incompatível, convertendo-as em valores exclusivos nas duas cadeias de entrada.

Pode ser ajustado, ou seja, no caso de tradução de namespaces. Mas, para os meus requisitos, apenas faz o trabalho.

TouDick
fonte
-2

Como você diz "equivalente semanticamente", suponho que você queira fazer mais do que apenas literalmente verificar se as saídas xml são (string) iguais e se deseja algo como

<foo> algumas coisas aqui </foo> </code>

e

<foo> algumas coisas aqui </foo> </code>

leia como equivalente. Por fim, importa como você está definindo "equivalente semanticamente" em qualquer objeto do qual reconstituir a mensagem. Simplesmente crie esse objeto a partir das mensagens e use um igual igual a () para definir o que você está procurando.

Steve B.
fonte
4
Não é uma resposta, mas uma pergunta.
Kartoch