두 개의 XML 파일을 다른 행에 있는 동일한 데이터와 비교하는 방법은 무엇입니까?

두 개의 XML 파일을 다른 행에 있는 동일한 데이터와 비교하는 방법은 무엇입니까?

데이터는 동일하지만 행이 다른 두 개의 파일이 있습니다.

파일 1:

<Identities>
    <Identity>
        <Id>048206031415072010Comcast.USR8JR</Id>
        <UID>ccp_test_79</UID>
        <DisplayName>JOSH CCP</DisplayName>
        <FirstName>JOSH</FirstName>
        <LastName>CCP</LastName>
        <Role>P</Role>
        <LoginStatus>C</LoginStatus>
    </Identity>
    <Identity>
        <Id>089612381523032011Comcast.USR1JR</Id>
        <UID>94701_account1</UID>
        <DisplayName>account1</DisplayName>
        <FirstName>account1</FirstName>
        <LastName>94701</LastName>
        <Role>S</Role>
        <LoginStatus>C</LoginStatus>
    </Identity>
</Identities>

파일 2:

<Identities>
    <Identity>
        <Id>089612381523032011Comcast.USR1JR</Id>
        <UID>94701_account1</UID>
        <DisplayName>account1</DisplayName>
        <FirstName>account1</FirstName>
        <LastName>94701</LastName>
        <Role>S</Role>
        <LoginStatus>C</LoginStatus>
    </Identity>
    <Identity>
        <Id>048206031415072010Comcast.USR8JR</Id>
        <UID>ccp_test_79</UID>
        <DisplayName>JOSH CCP</DisplayName>
        <FirstName>JOSH</FirstName>
        <LastName>CCP</LastName>
        <Role>P</Role>
        <LoginStatus>C</LoginStatus>
    </Identity>
</Identities>

diff file1 file2명령을 사용하면 다음과 같은 응답을 얻습니다.

1,10d0
<     <Identities>
<         <Identity>
<             <Id>048206031415072010Comcast.USR8JR</Id>
<             <UID>ccp_test_79</UID>
<             <DisplayName>JOSH CCP</DisplayName>
<             <FirstName>JOSH</FirstName>
<             <LastName>CCP</LastName>
<             <Role>P</Role>
<             <LoginStatus>C</LoginStatus>
<         </Identity>
20a11,20
>     <Identities>
>         <Identity>
>             <Id>048206031415072010Comcast.USR8JR</Id>
>             <UID>ccp_test_79</UID>
>             <DisplayName>JOSH CCP</DisplayName>
>             <FirstName>JOSH</FirstName>
>             <LastName>CCP</LastName>
>             <Role>P</Role>
>             <LoginStatus>C</LoginStatus>
>         </Identity>

그러나 파일의 다른 행에 동일한 데이터가 있으므로 차이를 얻을 필요가 없습니다.

답변1

작은 Python 스크립트의 도움으로 원하는 것을 얻을 수 있습니다(Python이 설치되어 있어야 하며,lxml툴킷).

tagsort.py:

#!/usr/bin/python

import sys
from lxml import etree

filename, tag = sys.argv[1:]

doc = etree.parse(filename, etree.XMLParser(remove_blank_text=True))
root = doc.getroot()
root[:] = sorted(root, key=lambda el: el.findtext(tag))
print etree.tostring(doc, pretty_print=True)

이 스크립트는 두 번째 수준 요소의 내용을 기반으로 XML 문서 루트 아래의 첫 번째 수준 요소를 정렬하고 결과를 stdout으로 보냅니다. 그 이름은 다음과 같습니다:

$ python tagsort.py filename tag

일단 익숙해지면 사용할 수 있습니다프로세스 교체출력을 기반으로 차이점을 가져옵니다(예제 파일에 요소 하나를 추가하고 비어 있지 않은 결과를 표시하기 위해 다른 요소를 변경했습니다).

$ diff <(python tagsort.py file1 Id) <(python tagsort.py file2 Id)
4a5
>     <AddedTag>Something</AddedTag>
17c18
<     <Role>X</Role>
---
>     <Role>S</Role>

답변2

비슷한 문제가 있었는데 마침내 다음을 발견했습니다.https://superuser.com/questions/79920/how-can-i-diff-two-xml-files

해당 기사에서는 먼저 표준 XML 정렬을 권장한 다음 비교를 수행합니다. Linux, Mac을 사용하거나 cygwin과 같은 Windows 시스템이 설치된 경우 다음이 적합합니다.

$ xmllint --c14n File1.xml > 1.xml
$ xmllint --c14n File2.xml > 2.xml
$ diff 1.xml 2.xml

답변3

쉘로 태그가 지정되어 있지만 솔직히 파서와 함께 스크립팅 언어를 사용하는 것을 선호합니다. 이 경우 perl에는 XML::Twig.

문제는 다음과 같습니다.

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

sub compare_by_identity {
   my ( $first, $second ) = @_;
   foreach my $identity ( $first->get_xpath('//Identity') ) {
      my $id = $identity->first_child_text('Id');

      print $id, "\n";
      my $compare_to =
        $second->get_xpath( "//Identity/Id[string()=\"$id\"]/..", 0 );
      if ($compare_to) {
         print "Matching element found for ID $id\n";
         foreach my $element ( $identity->children ) {
            my $tag  = $element->tag;
            my $text = $element->text;
            if ( not $element->text eq $compare_to->first_child_text($tag) ) {
               print "$id, $tag has value $text which doesn't match: ",
                 $compare_to->first_child_text($tag), "\n";
            }
         }
      }
      else {
         print "No matching element for Id $id\n";
      }
   }
}

my $first_file  = XML::Twig->new->parsefile('test1.xml');
my $second_file = XML::Twig->new->parsefile('test2.xml');

compare_by_identity( $first_file,  $second_file );
compare_by_identity( $second_file, $first_file );

한 번에 하나의 "ID" 요소를 명시적으로 비교하고 한 요소의 모든 필드가 다른 요소에 존재하고 동일한 값을 갖는지 확인합니다.

그런 다음 두 번째 파일 때문에 반대 방향으로가능한추가 항목이 있습니다.

답변4

xq다음에서 사용https://kislyuk.github.io/yq/:

xq -sS '.[].Identities.Identity |= sort | .[0] == .[1]' file1.xml file2.xml

두 개의 XML 파일을 읽고 JSON으로 변환합니다. 각 파일은 최상위 배열의 별도 요소로 표시되므로 위의 예에서는 다음 에서 file1.xml찾을 수 있습니다 ( 이 옵션을 통해 수행됨). 이 옵션을 사용하면 각 파일의 키가 자동으로 정렬됩니다 ..[0]file2.xml.[1]-s-S

각 문서의 신원을 정렬한 후 두 문서를 비교합니다.

출력은 true질문에 제공된 데이터 문자열이거나 false두 문서 중 하나가 변경된 경우입니다.

다음과 같이 쉘 테스트에서 사용할 수 있습니다.

if xq -e -sS '.[].Identities.Identity |= sort | .[0] == .[1]' file1.xml file2.xml >/dev/null
then
    echo 'documents are the same'
else
    echo 'documents are different'
fi

이 옵션을 사용하면 마지막 문에 -e종료 상태가 xq0인 경우 종료 상태가 0 이 됩니다.진짜부울 값.


참고로 문제의 두 파일에 대해 내부적으로 생성된 JSON 문서는 다음과 같습니다.

[
  {
    "Identities": {
      "Identity": [
        {
          "DisplayName": "JOSH CCP",
          "FirstName": "JOSH",
          "Id": "48206031415072010Comcast.USR8JR",
          "LastName": "CCP",
          "LoginStatus": "C",
          "Role": "P",
          "UID": "ccp_test_79"
        },
        {
          "DisplayName": "account1",
          "FirstName": "account1",
          "Id": "089612381523032011Comcast.USR1JR",
          "LastName": "94701",
          "LoginStatus": "C",
          "Role": "S",
          "UID": "94701_account1"
        }
      ]
    }
  },
  {
    "Identities": {
      "Identity": [
        {
          "DisplayName": "account1",
          "FirstName": "account1",
          "Id": "089612381523032011Comcast.USR1JR",
          "LastName": "94701",
          "LoginStatus": "C",
          "Role": "S",
          "UID": "94701_account1"
        },
        {
          "DisplayName": "JOSH CCP",
          "FirstName": "JOSH",
          "Id": "048206031415072010Comcast.USR8JR",
          "LastName": "CCP",
          "LoginStatus": "C",
          "Role": "P",
          "UID": "ccp_test_79"
        }
      ]
    }
  }
]

관련 정보