জাভাতে 2 টি এক্সএমএল ডকুমেন্টের তুলনা করার সেরা উপায়


198

আমি এমন একটি অ্যাপ্লিকেশনটির একটি স্বয়ংক্রিয় পরীক্ষা লেখার চেষ্টা করছি যা মূলত একটি কাস্টম বার্তা ফর্ম্যাটটি একটি এক্সএমএল বার্তায় অনুবাদ করে অন্য প্রান্তে প্রেরণ করে। আমি ইনপুট / আউটপুট বার্তা জোড়গুলির একটি ভাল সেট পেয়েছি তাই আমাকে যা করতে হবে তা হল ইনপুট বার্তাগুলি প্রেরণ করা এবং অন্য প্রান্তটি এক্সএমএল বার্তাটি শোনার জন্য শুনুন।

যখন আসার সময়টিকে প্রত্যাশিত আউটপুটটির সাথে তুলনা করার সময় আসে তখন আমি কিছু সমস্যার মধ্যে চলে আসছি। আমার প্রথম চিন্তাটি ছিল কেবলমাত্র প্রত্যাশিত এবং প্রকৃত বার্তাগুলির সাথে স্ট্রিং তুলনা করা। এটি খুব ভালভাবে কাজ করে না কারণ আমাদের কাছে থাকা উদাহরণস্বরূপ ডেটা সবসময় ধারাবাহিকভাবে ফর্ম্যাট হয় না এবং প্রায়শই XML নেমস্পেসের জন্য বিভিন্ন এলিয়াস ব্যবহার করা হয় (এবং কখনও কখনও নেমস্পেস ব্যবহার করা হয় না))

আমি জানি যে আমি উভয় স্ট্রিংকে বিশ্লেষণ করতে পারি এবং তারপরে প্রতিটি উপাদান দিয়ে চলতে পারি এবং সেগুলি নিজের সাথে তুলনা করতে পারি এবং এটি করা খুব কঠিন হবে না তবে আমার অনুভূতিটি পাওয়া যায় যে আমি উত্তোলন করতে পারি তার চেয়ে ভাল উপায় বা কোনও লাইব্রেরি।

সুতরাং, সিদ্ধ হয়ে, প্রশ্নটি হল:

দুটি জাভা স্ট্রিং দেওয়া হয়েছে যা উভয়টিতেই বৈধ এক্সএমএল রয়েছে তবে সেগুলি শব্দার্থত সমতুল্য কিনা তা নির্ধারণের জন্য আপনি কীভাবে যাবেন? পার্থক্য কী তা নির্ধারণ করার কোনও উপায় থাকলে বোনাস পয়েন্ট।

উত্তর:


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 নিয়ে সমস্যা ছিল, এটি এক্সএমএল এপিআই সংস্করণগুলির সাথে হাইপার-টুইচি এবং নির্ভরযোগ্য প্রমাণিত হয়নি। XOM এর জন্য এটিকে আঁকতে কিছুক্ষণ হয়ে গেছে, যদিও, সম্ভবত এটি পরে অভিশপ্ত।
স্কাফম্যান

63
এক্সএমএলউনিতের নতুনদের জন্য, নোট করুন যে ডিফল্টরূপে, মাইডিফ.সিমার () যদি নিয়ন্ত্রণ এবং পরীক্ষার নথিগুলি ইনডেন্টেশন / নিউলাইনগুলিতে পৃথক হয় তবে মিথ্যা ফিরিয়ে দেবে । আমি এই আচরণটি মাইডিফ.ডিসেন্টাল () থেকে প্রত্যাশা করেছিলাম, এবং মাইডিফ.সামার () থেকে নয়। XMLUnit.setIgnoreWhitespace (সত্য) অন্তর্ভুক্ত করুন; আপনার পরীক্ষার শ্রেণিতে সমস্ত পরীক্ষার জন্য আচরণটি পরিবর্তন করতে আপনার সেটআপ পদ্ধতিতে, বা কেবলমাত্র সেই পরীক্ষার জন্য আচরণটি পরিবর্তন করতে এটি একটি স্বতন্ত্র পরীক্ষা পদ্ধতিতে ব্যবহার করুন।
স্টিউ

1
@ আপনার মন্তব্যের জন্য পুনরায় ধন্যবাদ, এক্সএমএলইউনিত দিয়ে শুরু করে এবং নিশ্চিত যে এই সমস্যার মুখোমুখি হতে পেরেছি। +1
জয়

2
আপনি যদি গিথুবে এক্সএমএলউনিত 2 দিয়ে এটি চেষ্টা করছেন, 2 সংস্করণ এটি একটি সম্পূর্ণ পুনর্লিখন, সুতরাং এই উদাহরণটি সোর্সফোর্জে এক্সএমএলউনিত 1 এর জন্য। এছাড়াও, সোর্সফোজের পৃষ্ঠাটিতে "জাভা 1.x এর জন্য এক্সএমএলউইনটি এখনও বজায় রাখা হবে" states
ইয়াঙ্গ্বর ক্রিশ্চিয়েনসেন


36

নিম্নলিখিতটি স্ট্যান্ডার্ড জেডি কে লাইব্রেরি ব্যবহার করে নথিগুলি সমান কিনা তা পরীক্ষা করবে।

ডকুমেন্টবিল্ডারফ্যাক্টরি ডিবিএফ = ডকুমেন্টবিল্ডারফ্যাক্টরি.নাইআইএনস্ট্যান্স ();
dbf.setNamespaceAware (সত্য);
dbf.setCoalescing (সত্য);
dbf.setIgnoringElementContentWhitespace (সত্য);
dbf.setIgnoringComments (সত্য);
ডকুমেন্টবিল্ডার db = dbf.newDocamentBuilder ();

দস্তাবেজ ডক 1 = db.parse (নতুন ফাইল ("file1.xML"));
doc1.normalizeDocument ();

দস্তাবেজ ডক 2 = db.parse (নতুন ফাইল ("file2.xML"));
doc2.normalizeDocument ();

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

স্বাভাবিককরণ () কোনও চক্র নেই তা নিশ্চিত করার জন্য রয়েছে (প্রযুক্তিগতভাবে কোনও হবে না)

উপরের কোডটির জন্য উপাদানগুলির মধ্যে সাদা স্পেসগুলি একই হওয়া দরকার কারণ এটি এটি সংরক্ষণ করে এবং মূল্যায়ন করে। জাভা সহ যে স্ট্যান্ডার্ড এক্সএমএল পার্সার আসে সেটি আপনাকে একটি ক্যানোনিকাল সংস্করণ সরবরাহ করার জন্য কোনও বৈশিষ্ট্য সেট করার অনুমতি দেয় না বা বুঝতে পারে xml:spaceযদি এটি কোনও সমস্যা হয়ে চলেছে তবে আপনার প্রয়োজন হতে পারে এক্সপ্লেরার এক্সএমএল পার্সার যেমন জেরেস বা জেডিএম ব্যবহার করুন।


4
এটি পুরোপুরি এক্সএমএলগুলির জন্য নেমস্পেসগুলি ছাড়াই বা "নরমালাইজড" নেমস্পেস উপসর্গ সহ কাজ করে। আমি সন্দেহ করি যে এটি এক্সএমএল <এনএস 1: একটি এক্সএমএনএস: এনএস 1 = "এনএস" /> এবং অন্যটি হল <এনএস 2: একটি এক্সএমএনএস: এনএস 2 = "এনএস" />
কোপ্পোর 6:43

dbf.setIgnoringElementContentWhitespace (সত্য) এর ফলাফলটি আমি পাব না বলে আমি আশা করব <root> নাম </ro> এই সমাধানের সাথে <root> নাম </ name> সমান নয় (দুটি স্থানের সাথে প্যাডযুক্ত) তবে এক্সএমএলউনিত সমান ফলাফল দেয় এই ক্ষেত্রে (জেডিকে 8)
মিক্লোস

আমার জন্য এটি লাইন ব্রেকগুলি উপেক্ষা করে না, যা একটি সমস্যা।
ফ্লাইআউট 91

setIgnoringElementContentWhitespace(false)
আর্কিমিডিজ ট্রাজানো

28

এক্সমের একটি ক্যানোনিকালাইজার ইউটিলিটি রয়েছে যা আপনার ডোমগুলিকে একটি নিয়মিত ফর্মে রূপান্তরিত করে, যার পরে আপনি স্ট্রিংফাই করে তুলনা করতে পারবেন। তাই হোয়াইটস্পেসে অনিয়ম বা বৈশিষ্ট্য ক্রম নির্বিশেষে, আপনি আপনার নথির নিয়মিত, অনুমানযোগ্য তুলনা পেতে পারেন।

এটি আইডিইগুলিতে বিশেষভাবে ভাল কাজ করে যা উপগ্রহের মতো ডেডিকেটেড ভিজ্যুয়াল স্ট্রিং তুলনামূলক করে। আপনি দস্তাবেজের মধ্যে অর্থগত পার্থক্যগুলির একটি চাক্ষুষ উপস্থাপনা পান।


21

এক্সএমএলউনিতের সর্বশেষতম সংস্করণ দুটি এক্সএমএল সমান বলে জোর দেওয়ার কাজ করতে পারে। এছাড়াও 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());
    }

}

যদি মাভেন ব্যবহার করে থাকেন তবে এটিতে আপনার যুক্ত করুন pom.xml:

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

এটি এমন লোকদের জন্য উপযুক্ত যাঁকে একটি স্ট্যাটিক পদ্ধতি থেকে তুলনা করা প্রয়োজন।
অ্যান্ডি বি

এটি নিখুঁত উত্তর। আপনাকে ধন্যবাদ .. তবে আমার যে নোডগুলি বিদ্যমান নেই সেগুলি উপেক্ষা করতে হবে। যেহেতু আমি ফলাফলের আউটপুটে এই জাতীয় ফলাফল দেখতে চাই না: চাইল্ড নোডের উপস্থিতি "নাল" কিন্তু ছিল ...... আমি কীভাবে এটি করতে পারি? শুভেচ্ছা। @acdcjunior
লিমনিক

1
XMLUnit.setIgnoreAttributeOrder (সত্য); কাজ করে না. কিছু নোডের যদি আলাদা অর্ডার থাকে তবে তুলনাটি ব্যর্থ হবে।
22:37

[২] এই সমাধান কাজ করে: 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
বেশ দেরি হয়ে গেছে, তবে কেবল এই লক্ষ করতে চেয়েছিলেন যে এই কোডের টুকরোতে একটি বাগ রয়েছে: ডিফফনডস () এ, নোড 2 উল্লেখ করা হয় না - দ্বিতীয় লুপটি নোড 1 ভুলভাবে পুনরায় ব্যবহার করে (আমি এটি ঠিক করার জন্য কোডটি সম্পাদনা করেছি)। এছাড়াও, এর 1 টি সীমাবদ্ধতা রয়েছে: শিশু মানচিত্রে কী কীভাবে চালিত হয় সেই কারণে, উপাদানগুলির নামগুলি অনন্য নয়, অর্থাত্ পুনরাবৃত্তিযোগ্য শিশু উপাদান যুক্ত উপাদানগুলিকে এই ভিন্নতা সমর্থন করে না।
aberrant80

7

টমের উত্তরে বিল্ডিং , এখানে এক্সএমএলউইনটি ভি 2 ব্যবহার করে একটি উদাহরণ দেওয়া হয়েছে।

এটি এই 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#compering-two-documents


3

স্কাফম্যান ভাল উত্তর দিচ্ছে বলে মনে হচ্ছে।

আর একটি উপায় সম্ভবত এক্সএমএলকে xMLstarlet ( http://xMLstar.sourceforge.net/ ) এর মতো কম্যান্ড লাইন ইউটিলিটি ব্যবহার করে ফর্ম্যাট করা এবং তারপরে উভয় স্ট্রিংকে ফর্ম্যাট করে এবং তারপরে ফলাফল আউটপুট ফাইলগুলিকে পৃথক করতে কোনও ডিফ ইউটিলিটি (গ্রন্থাগার) ব্যবহার করতে হবে। আমি জানি না যখন সমস্যাগুলি নামের জায়গাগুলিতে থাকে তখন এটি ভাল সমাধান কিনা।



2

আমি আল্টোভা ডিফডগ ব্যবহার করছি যা এক্সএমএল ফাইলগুলিকে কাঠামোগতভাবে তুলনা করার বিকল্প রয়েছে (স্ট্রিং ডেটা উপেক্ষা করে)।

এর অর্থ হ'ল (যদি 'পাঠ্যটিকে উপেক্ষা করুন' বিকল্পটি পরীক্ষা করা হয়):

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

এবং

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

তারা কাঠামোগত সাম্য আছে যে অর্থে সমান। আপনার কাছে যদি এমন ফাইল রয়েছে যা ডাটাতে পৃথক, তবে কাঠামোগত নয়!


3
শুধুমাত্র বিয়োগটি হ'ল 30 দিনের পরীক্ষার মাধ্যমে এটি বিনামূল্যে নয় (প্রো লাইসেন্সের জন্য 99 license)।
পিমিন কনস্ট্যান্টিন কেফলালোকস

2
আমি কেবল ইউটিলিটিটি খুঁজে পেয়েছি ( altova.com/diffdog/diff- নিম-tool.html ); একটি লাইব্রেরি পেয়ে ভাল লাগল।
dma_k

1

এটি সম্পূর্ণ স্ট্রিং এক্সএমএলগুলির সাথে তুলনা করবে (পথে তাদের পুনরায় ফর্ম্যাট করা)। এটি আপনার আইডিই (ইন্টেলিজিজ, একলিপস) এর সাথে কাজ করা সহজ করে তোলে, আপনি কেবল ক্লিক করে এক্সএমএল ফাইলগুলির মধ্যে পার্থক্যটি দেখতে পান।

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 এ পছন্দ করি কারণ ক্লায়েন্ট কোড (পরীক্ষার কোড) পরিষ্কার থাকে clean


1
একই এক্সএমএল এবং বিভিন্ন এক্সএমএল সহ আমি এখন দুটি পরীক্ষায় এটি কাজ করে। ইন্টেলিজের পার্থক্য সহ এটি তুলনামূলক এক্সএমএলের পার্থক্যগুলি চিহ্নিত করা সহজ।
ইয়েঙ্গ্বর ক্রিশ্চিয়েনসেন

1
যাইহোক, আপনি যদি এই ম্যাভেন: <d depend depend> <groupId> org.apache.santuario </groupId> <artifactId> xmlsec </artifactId> <version> 2.0.6 </version> </ ব্যবহার করেন তবে আপনার এই নির্ভরতা দরকার নির্ভরতা>
ইয়াংভার ক্রিশ্চিয়েনসেন

1

নীচের কোডটি আমার জন্য কাজ করে

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

1
কোন প্রসঙ্গে? লাইব্রেরির রেফারেন্স?
বেন

0

জাভা অ্যাপ্লিকেশন সহ 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

মূল প্রশ্নের অনুরোধ অনুযায়ী আমার একই কার্যকারিতাটি দরকার ছিল। যেহেতু আমাকে তৃতীয় পক্ষের কোনও গ্রন্থাগার ব্যবহার করার অনুমতি দেওয়া হয়নি, আমি @ আর্কিমিডস ট্র্যাজনো সমাধানের ভিত্তিতে নিজস্ব সমাধান তৈরি করেছি have

নিম্নলিখিত আমার সমাধান।

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

}

এটি দুটি এক্সএমএল স্ট্রিংয়ের তুলনা করে এবং উভয় ইনপুট স্ট্রিংগুলিতে অনন্য মানগুলিতে অনুবাদ করে যেকোন অমিল নেমস্পেস ম্যাপিংগুলিকে যত্ন করে।

সূক্ষ্ম সুর করা যেতে পারে অর্থাত্ নেমস্পেসের অনুবাদ করার ক্ষেত্রে। তবে আমার প্রয়োজনীয়তার জন্য কেবল কাজটি করে।


-2

যেহেতু আপনি "শব্দার্থত সমতুল্য" বলছেন আমি ধরে নিলাম এর অর্থ আপনি যে XML আউটপুট (স্ট্রিং) সমান, এবং আপনি এর মতো কিছু চান তা কেবল আক্ষরিকভাবে যাচাই করার চেয়ে আরও কিছু করতে চান

<foo> এখানে কিছু জিনিস </ foo> </code>

এবং

<foo> এখানে কিছু জিনিস </ foo> </code>

সমান হিসাবে পড়া না। অবশেষে এটি আপনি ম্যাসেজটি পুনর্গঠন করছেন এমন কোনও বস্তুর উপর কীভাবে "শব্দার্থ সমতুল্য" সংজ্ঞা দিচ্ছেন তা গুরুত্বপূর্ণ matter বার্তাগুলি থেকে কেবল সেই অবজেক্টটি তৈরি করুন এবং আপনি যা খুঁজছেন তা নির্ধারণ করতে একটি কাস্টম সমান () ব্যবহার করুন।


4
উত্তর নয় বরং একটি প্রশ্ন।
কার্টোচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.