Java에서 2 개의 XML 문서를 비교하는 가장 좋은 방법


198

기본적으로 사용자 정의 메시지 형식을 XML 메시지로 변환하고 다른 쪽 끝으로 보내는 응용 프로그램의 자동화 된 테스트를 작성하려고합니다. 입력 / 출력 메시지 쌍이 잘 갖추어져 있으므로 입력 메시지를 보내고 XML 메시지를 듣고 다른 쪽 끝을 듣기 만하면됩니다.

실제 출력을 예상 출력과 비교할 때가되었지만 몇 가지 문제가 있습니다. 내 첫 번째 생각은 예상 된 메시지와 실제 메시지를 문자열 비교하는 것입니다. 우리가 가지고있는 예제 데이터가 항상 일관되게 형식화되지는 않으며 XML 네임 스페이스에 다른 별칭이 사용되는 경우가 종종 있으며 때로는 네임 스페이스가 전혀 사용되지 않기 때문에 이것은 잘 작동하지 않습니다.

두 문자열을 구문 분석 한 다음 각 요소를 살펴보고 직접 비교할 수 있으며 그렇게하기가 어렵지 않지만 더 좋은 방법이나 라이브러리를 활용할 수 있다는 느낌이 들었습니다.

따라서 삶은 문제는 다음과 같습니다.

둘 다 유효한 XML을 포함하는 두 개의 Java 문자열이 주어지면 의미 적으로 동등한 지 여부를 어떻게 결정합니까? 차이점을 확인할 수있는 방법이 있다면 보너스 포인트입니다.

답변:


197

XMLUnit의 일처럼 들린다

예:

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
과거에 XMLUNit에 문제가 있었지만 XML API 버전에서는 매우 복잡했으며 신뢰성이 입증되지 않았습니다. XOM을 위해 그것을 버린 지 오래되었습니다. 그래서 그 이후로 발전했을 것입니다.
skaffman

63
XMLUnit 초보자 는 제어 및 테스트 문서가 들여 쓰기 / 줄 바꾸기가 다른 경우 기본적으로 myDiff.similar ()가 false 를 반환 합니다. myDiff.similar ()가 아니라 myDiff.identical ()에서이 동작을 예상했습니다. XMLUnit.setIgnoreWhitespace (true)를 포함하십시오. setUp 메소드에서 테스트 클래스의 모든 테스트에 대한 동작을 변경하거나 개별 테스트 메소드에서이를 사용하여 해당 테스트에 대한 동작을 변경하십시오.
스튜

1
@ XMLUnit부터 시작하여 귀하의 의견에 감사드립니다.이 문제에 직면했을 것입니다. +1
Jay

2
github의 XMLUnit 2 로이 작업을 시도하는 경우 2 버전은 완전히 다시 작성 되므로이 예제는 SourceForge의 XMLUnit 1에 대한 것입니다. 또한 sourceforge 페이지에는 "XMLUnit for Java 1.x는 계속 유지됩니다"라고 표시되어 있습니다.
Yngvar Kristiansen

1
메소드는 XMLAssert.java에서와 같이 assertXMLEqual 입니다.
user2818782

36

다음은 표준 JDK 라이브러리를 사용하여 문서가 동일한 지 확인합니다.

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

문서 doc1 = db.parse (새 파일 ( "file1.xml"));
doc1.normalizeDocument ();

문서 doc2 = db.parse (새 파일 ( "file2.xml"));
doc2.normalizeDocument ();

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

normalize () 사이클이 없는지 확인하기 위해 존재합니다 (기술적으로는 없을 것입니다)

위의 코드는 공백을 유지하고 평가하기 때문에 요소 내에서 공백이 동일해야합니다. Java와 함께 제공되는 표준 XML 파서는 표준 버전을 제공하는 기능을 설정하거나 xml:space이것이 문제가 될지 이해하지 못 하므로 xerces와 같은 대체 XML 파서가 필요하거나 JDOM을 사용해야합니다.


4
네임 스페이스가 없거나 "정규화 된"네임 스페이스 접두사가있는 XML에 완벽하게 작동합니다. 하나의 XML이 <ns1 : a xmlns : ns1 = "ns"/>이고 다른 하나가 <ns2 : a xmlns : ns2 = "ns"/> 인 경우 작동하는지 의심합니다.
koppor

dbf.setIgnoringElementContentWhitespace (true)에는 결과가 없습니다.이 솔루션에서 <root> name </ root>이 <root> name </ name>과 같지 않을 것으로 예상되지만 XMLUnit은 동일한 결과를 제공합니다 이 경우 (JDK8)
Miklos Krivan

나에게 그것은 줄 바꿈을 무시하지 않는다. 이것은 문제이다.
Flyout91

setIgnoringElementContentWhitespace(false)
Archimedes Trajano

28

Xom 에는 Canonicalizer 유틸리티가있어 DOM을 일반 형식으로 변환하여 문자열 화하고 비교할 수 있습니다. 따라서 공백의 불규칙성 또는 속성 순서에 관계없이 문서를 정기적으로 예측 가능한 비교할 수 있습니다.

이것은 Eclipse와 같은 전용 시각적 문자열 비교기가있는 IDE에서 특히 잘 작동합니다. 문서 간의 시맨틱 차이를 시각적으로 표시합니다.


21

최신 버전의 XMLUnit 은 두 XML을 동일하게 주장하는 작업에 도움이 될 수 있습니다. 또한 XMLUnit.setIgnoreWhitespace()XMLUnit.setIgnoreAttributeOrder()문제의 경우에 필요할 수 있습니다.

아래의 XML 단위 사용에 대한 간단한 예의 작업 코드를 참조하십시오.

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

}

Maven을 사용하는 경우 이것을 다음에 추가하십시오 pom.xml.

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

이것은 정적 방법과 비교 해야하는 사람들에게 완벽합니다.
Andy B

이것은 완벽한 대답입니다. 감사합니다. 그러나 존재하지 않는 노드는 무시해야합니다. 결과 출력에서 ​​그러한 출력을보고 싶지 않기 때문에 : 자식 노드 "null"의 존재가 있었지만 ......... 어떻게 할 수 있습니까? 문안 인사. @acdcjunior
limonik

1
XMLUnit.setIgnoreAttributeOrder (true); 작동하지 않습니다. 일부 노드의 순서가 다른 경우 비교에 실패합니다.
Bevor

[업데이트]이 솔루션은 작동합니다 : stackoverflow.com/questions/33695041/…
Bevor

"IgnoreAttributeOrder"는 속성 순서를 무시하고 노드 순서를 무시하지 않음을 의미합니다.
acdcjunior

7

고마워, 나는 이것을 확장, 이것을 시도 ...

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
꽤 늦었지만이 코드 조각에 버그가 있음을 알고 싶었습니다. diffNodes ()에서 node2는 참조되지 않습니다. 두 번째 루프는 node1을 잘못 재사용합니다 (이 문제를 해결하기 위해 코드를 편집했습니다). 또한 한 가지 제한 사항이 있습니다. 자식 맵으로 키가 지정되는 방식으로 인해이 diff는 요소 이름이 고유하지 않은 경우 (예 : 반복 가능한 자식 요소를 포함하는 요소)를 지원하지 않습니다.
aberrant80

7

바탕 의 대답은 여기에 위해 XMLUnit의 V2를 사용하는 예제입니다.

이 maven 의존성을 사용합니다

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

테스트 코드는 다음과 같습니다.

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

이를 설명하는 문서는 https://github.com/xmlunit/xmlunit#comparing-two-documents입니다.


3

skaffman이 좋은 대답을하고있는 것 같습니다.

다른 방법은 xmlstarlet ( http://xmlstar.sourceforge.net/ )과 같은 명령 줄 유틸리티를 사용하여 XML을 포맷 한 다음 두 문자열을 모두 포맷 한 다음 diff 유틸리티 (라이브러리)를 사용하여 결과 출력 파일을 비교하는 것입니다. 네임 스페이스에 문제가있을 때 이것이 좋은 해결책인지는 모르겠습니다.



2

내가 사용하고 Altova DiffDog 구조적 (문자열 데이터를 무시) XML 파일을 비교하는 옵션이 있습니다.

이는 ( '텍스트 무시'옵션을 선택한 경우) :

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

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

그들이 구조적 평등을 가지고 있다는 점에서 평등합니다. 데이터가 다르지만 구조가 아닌 예제 파일이있는 경우 편리합니다!


3
마이너스 만이 30 일 평가판으로 무료가 아닙니다 (프로 라이센스의 경우 99 €).
Pimin Konstantin Kefaloukos

2
유틸리티 만 발견했습니다 ( altova.com/diffdog/diff-merge-tool.html ). 도서관을 가지고 반갑습니다.
dma_k

1

이것은 전체 문자열 XML을 비교합니다 (가는 길에 다시 포맷). 클릭하면 XML 파일의 차이점을 시각적으로 볼 수 있으므로 IDE (IntelliJ, Eclipse)와 함께 쉽게 작업 할 수 있습니다.

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

클라이언트 코드 (테스트 코드)가 더 깨끗하기 때문에 이것을 XmlUnit보다 선호합니다.


1
이것은 동일한 XML과 다른 XML로 내가 지금 한 두 가지 테스트에서 잘 작동합니다. IntelliJ diff를 사용하면 비교 XML의 차이점을 쉽게 알 수 있습니다.
Yngvar Kristiansen 님이

1
그런데 Maven을 사용하는 경우이 종속성이 필요합니다. <dependency> <groupId> org.apache.santuario </ groupId> <artifactId> xmlsec </ artifactId> <version> 2.0.6 </ version> </ 의존성>
Yngvar Kristiansen이

1

아래 코드는 저에게 효과적입니다.

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

1
어떤 맥락? 도서관 참조?
Ben

0

Java 애플리케이션에서 JExamXML 사용

    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

주요 질문에서 요청한 것과 동일한 기능이 필요했습니다. 타사 라이브러리를 사용할 수 없으므로 @Archimedes Trajano 솔루션을 기반으로 자체 솔루션을 만들었습니다.

다음은 내 해결책입니다.

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

}

두 개의 XML 문자열을 비교하고 일치하지 않는 네임 스페이스 매핑을 두 입력 문자열의 고유 한 값으로 변환하여 처리합니다.

네임 스페이스를 번역 할 때와 같이 미세 조정될 수 있습니다. 그러나 내 요구 사항에 따라 작업이 수행됩니다.


-2

"의미 적으로 동등한"이라고 말했기 때문에 XML 출력이 (문자열) 같은지, 문자 그대로 같은 것을 원한다는 것을 문자 그대로 확인하는 것 이상의 것을 원한다고 가정합니다.

<foo> 여기 몇 가지 </ foo> </ code>

<foo> 여기 물건 </ foo> </ code>

동등한 것으로 읽습니다. 궁극적으로 메시지를 재구성하는 객체에 대해 "의미 적으로 동등한"방법을 정의하는 것이 중요합니다. 메시지에서 해당 객체를 빌드하고 원하는 equals ()를 사용하여 원하는 것을 정의하십시오.


4
대답이 아니라 질문입니다.
Kartoch
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.