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.