programing

두 XML 문서를 어떻게 비교하시겠습니까?

padding 2023. 11. 4. 10:18
반응형

두 XML 문서를 어떻게 비교하시겠습니까?

광범위한 단위 테스트를 위한 기본 클래스의 일부로, 저는 C#(.NET)에 있는 XmlDocument 객체의 노드를 재귀적으로 비교하는 헬퍼 함수를 작성합니다.이에 대한 몇 가지 요구 사항:

  • 첫번째 문서는 출처입니다. 예를 들어 XML 문서가 어떤 모습을 가질지 말입니다.따라서 두 번째는 차이점을 찾고 싶은 것이고 첫 번째 문서에 추가 노드가 포함되지 않아야 합니다.
  • 너무 많은 중요한 차이점이 발견되면 예외를 두어야 하며, 설명을 보는 사람이 쉽게 이해할 수 있어야 합니다.
  • 하위 요소 순서가 중요합니다. 속성은 순서에 상관없이 사용할 수 있습니다.
  • 일부 특성은 무시할 수 있습니다. 특히,xsi:schemaLocation그리고.xmlns:xsi, 나는 어떤 것들이 있는 곳을 통과할 수 있기를 바라지만.
  • 네임스페이스의 접두사는 특성과 요소 모두에서 일치해야 합니다.
  • 요소 사이의 공백은 무관합니다.
  • 요소에 하위 요소가 있거나 InnerText, 둘 다 아닙니다.

제가 함께 무언가를 폐기하는 동안: 그런 코드를 작성한 사람이 있습니까? 그리고 여기서 공유할 수 있습니까?

덧붙여서, 첫 번째와 두 번째 문서를 뭐라고 부르겠습니까?저는 그들을 "source"와 "target"이라고 언급해 왔지만, source는 제가 원하는 target의 모습이기 때문에 잘못된 느낌이 듭니다. 그렇지 않으면 예외를 던집니다.

Microsoft에는 사용할 수 있는 XML diff API가 있습니다.

비공식 NuGet: https://www.nuget.org/packages/XMLDiffPatch .

오늘 이 문제에 대한 보다 완벽한 해결책 목록을 검색했는데, 곧 그 중 하나를 시도해 볼 예정입니다.

이 코드는 당신의 요구사항을 모두 만족시키지는 못하지만, 간단해서 유닛 테스트에 사용하고 있습니다.속성 순서는 중요하지 않지만 요소 순서는 중요합니다.요소 내부 텍스트를 비교하지 않습니다.속성을 비교할 때도 대소문자를 무시했지만, 쉽게 삭제할 수 있습니다.

public bool XMLCompare(XElement primary, XElement secondary)
{
    if (primary.HasAttributes) {
        if (primary.Attributes().Count() != secondary.Attributes().Count())
            return false;
        foreach (XAttribute attr in primary.Attributes()) {
            if (secondary.Attribute(attr.Name.LocalName) == null)
                return false;
            if (attr.Value.ToLower() != secondary.Attribute(attr.Name.LocalName).Value.ToLower())
                return false;
        }
    }
    if (primary.HasElements) {
        if (primary.Elements().Count() != secondary.Elements().Count())
            return false;
        for (var i = 0; i <= primary.Elements().Count() - 1; i++) {
            if (XMLCompare(primary.Elements().Skip(i).Take(1).Single(), secondary.Elements().Skip(i).Take(1).Single()) == false)
                return false;
        }
    }
    return true;
}

XML 유닛을 사용해 보십시오.이 라이브러리는 Java 와 .Net 둘다 사용할 수 있습니다.

자동화된 테스트에서 두 XML 출력을 비교하기 위해 발견했습니다.XNode.DeepEquals.

모든 하위 노드의 값을 포함하여 두 노드의 값을 비교합니다.

용도:

var xDoc1 = XDocument.Parse(xmlString1);
var xDoc2 = XDocument.Parse(xmlString2);

bool isSame = XNode.DeepEquals(xDoc1.Document, xDoc2.Document);
//Assert.IsTrue(isSame);

참조 : https://learn.microsoft.com/en-us/dotnet/api/system.xml.linq.xnode.deepequals?view=netcore-2.2

XML 문서를 비교하는 것은 복잡합니다.구글 for xmldiff (Microsoft 솔루션도 있음) 일부 도구.몇 가지 방법으로 해결했습니다.XSLT를 사용하여 요소와 속성을 정렬하고(때로는 다른 순서로 나타나기 때문에) 비교하고 싶지 않은 속성을 필터링한 다음 XML::Diff 또는 XML::SemanticDiff perl 모듈을 사용하거나 각 문서를 다른 줄에 있는 모든 요소와 속성으로 인쇄했습니다.유닉스 명령줄을 사용하면 결과가 달라집니다.

https://github.com/CameronWills/FatAntelope Microsoft XML Diff API의 또 다른 대체 라이브러리이것은 두 개의 XML 문서를 순서에 맞게 비교하고 최적의 일치를 만들어낼 수 있는 XML 디핑 알고리즘을 가지고 있습니다.

http://pages.cs.wisc.edu/ ~yuanwang/xdiff 여기에 설명된 X-Diff 알고리즘의 C# 포트입니다.

면책 사항:제가 썼어요 :)

또 다른 방법은...

  1. 두 파일의 내용을 서로 다른 두 문자열로 가져옵니다.
  2. XSLT(모든 것을 두 개의 새 문자열로 복사)를 사용하여 문자열을 변환합니다.이렇게 하면 요소 외부의 모든 공간이 제거됩니다.이렇게 하면 두 개의 새로운 문자열이 생성됩니다.
  3. 자, 두 줄을 서로 비교해 보세요.

이렇게 하면 차이의 정확한 위치를 알 수 없지만, 차이가 있는지만 알고 싶다면 타사 라이브러리 없이도 쉽게 수행할 수 있습니다.

저는 ExamX를 사용하고 있습니다.XML 파일을 비교하기 위한 ML입니다.한번 해보세요.저자인 A7Soft는 XML 파일을 비교하기 위한 API도 제공합니다.

현재 하위 순서를 무시하기 때문에 OP와 관련이 없지만 코드 전용 솔루션을 원한다면 제가 다소 잘못 개발한 Xml Specification Compare를 시도해 볼 수 있습니다.

위의 답변들은 모두 도움이 되지만 두 XML 파일의 차이를 확인하기 위해 Nuget 패키지를 사용하기 쉬워 보이는 XML Unit을 시도해보았는데, 여기 C# 샘플 코드가 있습니다.

public static bool CheckXMLDifference(string xmlInput, string xmlOutput)
    {
        Diff myDiff = DiffBuilder.Compare(Input.FromString(xmlInput))
            .WithTest(Input.FromString(xmlOutput))
            .CheckForSimilar().CheckForIdentical()
            .IgnoreComments()
            .IgnoreWhitespace().NormalizeWhitespace().Build();

        if(myDiff.Differences.Count() == 0)
        {
            // when there is no difference 
            // files are identical, return true;
            return true;
        }
        else
        {
            //return false when there is 1 or more difference in file
            return false;
        }

    }

테스트를 원하는 사람이 있다면 이를 사용하여 온라인 도구도 만들었으니 여기에서 확인할 수 있습니다.

https://www.minify-beautify.com/online-xml-difference

@TwoCents 답변을 기반으로 하고 이 링크를 사용하여 XML 정렬을 함으로써 나는 나만의 Xml 비교기를 만들었습니다.

XML 프로그램 비교

private static bool compareXML(XmlNode node, XmlNode comparenode)
    {

        if (node.Value != comparenode.Value)
            return false;

            if (node.Attributes.Count>0)
            {
                foreach (XmlAttribute parentnodeattribute in node.Attributes)
                {
                    string parentattributename = parentnodeattribute.Name;
                    string parentattributevalue = parentnodeattribute.Value;
                    if (parentattributevalue != comparenode.Attributes[parentattributename].Value)
                    {
                        return false;
                    }

                }

            }

          if(node.HasChildNodes)
            {
            sortXML(comparenode);
            if (node.ChildNodes.Count != comparenode.ChildNodes.Count)
                return false;
            for(int i=0; i<node.ChildNodes.Count;i++)
                {

                string name = node.ChildNodes[i].LocalName;
                if (compareXML(node.ChildNodes[i], comparenode.ChildNodes[i]) == false)
                    return false;
                }

            }



        return true;
    }

XML 프로그램 정렬

 private static void sortXML(XmlNode documentElement)
    {
        int i = 1;
        SortAttributes(documentElement.Attributes);
        SortElements(documentElement);
        foreach (XmlNode childNode in documentElement.ChildNodes)
        {
            sortXML(childNode);

        }
    }



  private static void SortElements(XmlNode rootNode)
    {



            for(int j = 0; j < rootNode.ChildNodes.Count; j++) {
                for (int i = 1; i < rootNode.ChildNodes.Count; i++)
                {
                    if (String.Compare(rootNode.ChildNodes[i].Name, rootNode.ChildNodes[1 - 1].Name) < 0)
                    {
                        rootNode.InsertBefore(rootNode.ChildNodes[i], rootNode.ChildNodes[i - 1]);

                    }


                }
            }
           // Console.WriteLine(j++);


    }
 private static void SortAttributes(XmlAttributeCollection attribCol)
    {
        if (attribCol == null)
            return;
        bool changed = true;
        while (changed)
        {
            changed = false;
            for (int i = 1; i < attribCol.Count; i++)
        {
                if (String.Compare(attribCol[i].Name, attribCol[i - 1].Name) < 0)
                {
                    //Replace
                    attribCol.InsertBefore(attribCol[i], attribCol[i - 1]);
                    changed = true;

                }
            }
        }
    }

저는 이 xml 비교 문제를 XSLT 1.0을 사용하여 해결하였습니다. XSLT 1.0은 순서가 없는 트리 비교 알고리즘을 사용하여 큰 xml 파일을 비교하는데 사용할 수 있습니다.https://github.com/sflynn1812/xslt-diff-turbo

언급URL : https://stackoverflow.com/questions/167946/how-would-you-compare-two-xml-documents

반응형