Najlepszy sposób na porównanie 2 dokumentów XML w Javie


198

Próbuję napisać automatyczny test aplikacji, który w zasadzie tłumaczy niestandardowy format wiadomości na komunikat XML i wysyła go na drugi koniec. Mam dobry zestaw par komunikatów wejściowych / wyjściowych, więc wszystko, co muszę zrobić, to wysłać wiadomości wejściowe i nasłuchiwać wiadomości XML wychodzącej z drugiego końca.

Kiedy przychodzi czas na porównanie rzeczywistej mocy wyjściowej z oczekiwaną, mam problemy. Moją pierwszą myślą było po prostu porównanie ciągów oczekiwanych i rzeczywistych komunikatów. Nie działa to zbyt dobrze, ponieważ przykładowe dane, które mamy, nie zawsze są konsekwentnie formatowane i często zdarza się, że w przestrzeni nazw XML stosowane są różne aliasy (a czasami przestrzenie nazw wcale nie są używane).

Wiem, że mogę przeanalizować oba ciągi, a następnie przejść przez każdy element i porównać je osobiście, co nie byłoby zbyt trudne, ale mam wrażenie, że istnieje lepszy sposób lub biblioteka, którą mógłbym wykorzystać.

Sprowadzone pytanie brzmi:

Biorąc pod uwagę dwa ciągi Java, które zawierają poprawny kod XML, jak byś zajął się określaniem, czy są one semantycznie równoważne? Punkty bonusowe, jeśli potrafisz określić różnice.

Odpowiedzi:


197

Brzmi jak zadanie dla XMLUnit

Przykład:

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
  }
}

1
W przeszłości miałem problemy z XMLUNit, było bardzo niepewnie z wersjami XML API i nie okazało się niezawodne. Minęło trochę czasu, odkąd porzuciłem go dla XOM, więc może od tamtej pory jest to polepszone.
— skaffman

63
Dla początkujących XMLUnit, należy pamiętać, że domyślnie myDiff.similar () zwróci false, jeśli dokumenty kontrolne i testowe różnią się wcięciem / znakami nowej linii. Oczekiwałem tego zachowania od myDiff.identical (), a nie od myDiff.similar (). Uwzględnij XMLUnit.setIgnoreWhitespace (true); w metodzie setUp, aby zmienić zachowanie wszystkich testów w klasie testowej, lub użyj go w indywidualnej metodzie testowej, aby zmienić zachowanie tylko dla tego testu.
— Gulasz

1
@ Dziękuję za komentarz, zaczynając od XMLUnit i jestem pewien, że napotkałbym ten problem. +1
— Jay

2
Jeśli próbujesz tego z XMLUnit 2 na github, wersja 2 to kompletne przepisanie, więc ten przykład dotyczy XMLUnit 1 na SourceForge. Ponadto strona sourceforge stwierdza „XMLUnit dla Java 1.x będzie nadal utrzymywany”.
— Yngvar Kristiansen

1
Metoda jest assertXMLEqual jak z XMLAssert.java .
— user2818782,

36

Poniższe sprawdzi, czy dokumenty są równe przy użyciu standardowych bibliotek JDK.

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

Dokument doc1 = db.parse (nowy plik („plik1.xml”));
doc1.normalizeDocument ();

Dokument doc2 = db.parse (nowy plik („plik2.xml”));
doc2.normalizeDocument ();

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

normalize () jest po to, aby upewnić się, że nie ma cykli (technicznie nie byłoby żadnych)

Powyższy kod wymaga jednak, aby białe spacje były takie same w elementach, ponieważ zachowuje je i ocenia. Standardowy analizator XML dostarczany z Javą nie pozwala ustawić funkcji zapewniającej wersję kanoniczną ani zrozumieć, xml:spaceczy to będzie problem, wtedy może być potrzebny zastępczy analizator XML, taki jak xerces, lub użyj JDOM.


4
To doskonale działa w przypadku plików XML bez przestrzeni nazw lub ze „znormalizowanymi” prefiksami przestrzeni nazw. Wątpię, czy to działa, jeśli jeden XML to <ns1: a xmlns: ns1 = "ns" /> a drugi to <ns2: a xmlns: ns2 = "ns" />
— koppor

dbf.setIgnoringElementContentWhitespace (true) nie daje wyniku Oczekiwałbym, że <katalog główny> nazwa </root> nie jest równy <katalog główny> nazwa </name> z tym rozwiązaniem (wypełnionym dwoma spacjami), ale XMLUnit daje taki sam wynik w tym przypadku (JDK8)
— Miklos Krivan

Dla mnie nie ignoruje podziałów linii, co stanowi problem.
— Flyout91,

setIgnoringElementContentWhitespace(false)
— Archimedes Trajano,

28

Xom ma narzędzie Canonicalizer, które zamienia DOM w zwykłą formę, którą można następnie skreślić i porównać. Niezależnie od nieprawidłowości białych znaków i kolejności atrybutów, możesz uzyskać regularne, przewidywalne porównania swoich dokumentów.

Działa to szczególnie dobrze w IDE, które mają dedykowane wizualne komparatory napisów, takie jak Eclipse. Otrzymasz wizualną reprezentację różnic semantycznych między dokumentami.


21

Najnowsza wersja XMLUnit może pomóc w zapewnieniu dwóch XML-ów. Również XMLUnit.setIgnoreWhitespace()i XMLUnit.setIgnoreAttributeOrder()może być konieczne w danym przypadku.

Zobacz działający kod prostego przykładu użycia Jednostki XML poniżej.

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());
    }

}

Jeśli używasz Maven, dodaj to do pom.xml:

<dependency>
    <groupId>xmlunit</groupId>
    <artifactId>xmlunit</artifactId>
    <version>1.4</version>
</dependency>

Jest to idealne rozwiązanie dla osób, które muszą porównać metodę statyczną.
— Andy B,

To idealna odpowiedź. Dziękuję .. Jednak muszę zignorować węzły, które nie istnieją. Ponieważ nie chcę widzieć w wynikowym wyniku takiego wyniku: Oczekiwana obecność węzła potomnego „null”, ale była ...... Jak to zrobić? Pozdrowienia. @acdcjunior
— limonik

1
XMLUnit.setIgnoreAttributeOrder (true); nie działa. Jeśli niektóre węzły mają inną kolejność, porównanie się nie powiedzie.
— Bevor

[AKTUALIZACJA] to rozwiązanie działa: stackoverflow.com/questions/33695041/…
— Bevor

Zdajesz sobie sprawę, że „IgnoreAttributeOrder” oznacza ignoruj ​​kolejność atrybutów, a nie ignoruj ​​kolejność węzłów, prawda?
— acdcjunior

7

Dzięki, rozszerzyłem to, spróbuj tego ...

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();
    }
}

3
Dość późno, ale chciałem zauważyć, że ten fragment kodu ma błąd: W diffNodes (), węzeł2 nie jest przywoływany - druga pętla ponownie używa węzła1 niepoprawnie (edytowałem kod, aby to naprawić). Ma również 1 ograniczenie: Ze względu na sposób, w jaki mapy potomne są kluczowane, ta różnica nie obsługuje przypadku, w którym nazwy elementów nie są unikalne, tj. Elementy zawierające powtarzalne elementy potomne.
— aberrant80

7

Opierając się na odpowiedzi Toma , oto przykład użycia XMLUnit v2.

Wykorzystuje te zależności od raju

    <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>

..i oto kod testowy

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
    }
}

Dokumentacja, która to określa, to https://github.com/xmlunit/xmlunit#comparing-two-documents


3

wydaje się, że skaffman daje dobrą odpowiedź.

innym sposobem jest prawdopodobnie sformatowanie XML za pomocą narzędzia linii poleceń, takiego jak xmlstarlet ( http://xmlstar.sourceforge.net/ ), a następnie sformatowanie obu ciągów, a następnie użycie dowolnego narzędzia (biblioteki) diff do różnicowania powstałych plików wyjściowych. Nie wiem, czy to dobre rozwiązanie, gdy występują problemy z przestrzeniami nazw.



2

Używam Altova DiffDog, który ma opcje strukturalnego porównywania plików XML (ignorowanie danych ciągu).

Oznacza to, że (jeśli zaznaczysz opcję „zignoruj ​​tekst”):

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

i

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

są równi w tym sensie, że mają równość strukturalną. Jest to przydatne, jeśli masz przykładowe pliki, które różnią się danymi, ale nie mają struktury!


3
Jedynym minusem jest to, że nie jest bezpłatny (99 € dla licencji pro), z 30-dniową wersją próbną.
— Pimin Konstantin Kefaloukos

2
Znalazłem tylko narzędzie ( altova.com/diffdog/diff-merge-tool.html ); miło mieć bibliotekę.
— dma_k

1

Spowoduje to porównanie pełnych ciągów plików XML (ich formatowanie po drodze). Ułatwia pracę z twoim IDE (IntelliJ, Eclipse), ponieważ wystarczy kliknąć i zobaczyć różnicę w plikach 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);
    }
}

Wolę to niż XmlUnit, ponieważ kod klienta (kod testowy) jest czystszy.


1
Działa to dobrze w dwóch testach, które zrobiłem teraz, z tym samym XML i innym XML. Dzięki IntelliJ diff różnice w porównywanym pliku XML są łatwe do wykrycia.
— Yngvar Kristiansen

1
Nawiasem mówiąc, będziesz potrzebować tej zależności, jeśli korzystasz z Maven: <dependency> <groupId> org.apache.santuario </groupId> <artifactId> xmlsec </artifactId> <version> 2.0.6 </version> </ zależność>
— Yngvar Kristiansen

1

Poniższy kod działa dla mnie

String xml1 = ...
String xml2 = ...
XMLUnit.setIgnoreWhitespace(true);
XMLUnit.setIgnoreAttributeOrder(true);
XMLAssert.assertXMLEqual(actualxml, xmlInDb);

1
Jakiś kontekst? Odniesienie do biblioteki?
— Ben

0

Używanie JExamXML z aplikacją 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 ) );

0

Wymagałem takiej samej funkcjonalności, jak wymagana w pytaniu głównym. Ponieważ nie mogłem korzystać z żadnych bibliotek stron trzecich, stworzyłem własne rozwiązanie w oparciu o rozwiązanie @Archimedes Trajano.

Oto moje rozwiązanie.

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));
            }
        }
    }

}

Porównuje dwa ciągi XML i dba o wszelkie niedopasowane odwzorowania przestrzeni nazw, tłumacząc je na unikalne wartości w obu ciągach wejściowych.

Można go dostroić, np. W przypadku tłumaczenia przestrzeni nazw. Ale według moich wymagań po prostu działa.


-2

Ponieważ mówisz „semantycznie równoważny”, zakładam, że masz na myśli, że chcesz zrobić coś więcej niż po prostu dosłownie sprawdzić, czy dane wyjściowe xml są (ciąg) równe i że chcesz czegoś takiego

<foo> kilka rzeczy tutaj </foo> </code>

i

<foo> kilka rzeczy tutaj </foo> </code>

czytaj jako równoważne. Ostatecznie będzie miało znaczenie, w jaki sposób definiujesz „semantycznie równoważny” dla dowolnego obiektu, z którego odtwarzana jest wiadomość. Po prostu zbuduj ten obiekt z wiadomości i użyj niestandardowego znaku równości (), aby zdefiniować to, czego szukasz.


4
Nie odpowiedź, ale pytanie.
— Kartoch
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.