データは同じですが、行が異なる2つのファイルがあります。
ファイル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)
このスクリプトは、2 番目のレベル要素の内容に基づいて XML ドキュメントのルートの下の最初のレベル要素をソートし、結果を stdout に送信します。その名前は次のとおりです。
$ python tagsort.py filename tag
慣れたら使えますプロセスの交換出力に基づいて違いを取得します(例ファイルに1つの要素を追加し、空でない結果を表示するために他の要素を変更しました)。
$ 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 );
一度に1つの「ID」要素を明示的に比較し、1つの要素のすべてのフィールドが別の要素に存在し、同じ値を持つことを確認します。
その後、2番目のファイルのために反対方向に可能追加の項目があります。
答え4
xq
以下で使用https://kislyuk.github.io/yq/:
xq -sS '.[].Identities.Identity |= sort | .[0] == .[1]' file1.xml file2.xml
2つのXMLファイルを読み取り、JSONに変換します。各ファイルは最上位配列の別々の要素として表示されるため、上記の例では次のようになりますfile1.xml
(このオプションで実行されます)。このオプションを使用すると、各ファイルのキーが自動的にソートされます。.[0]
file2.xml
.[1]
-s
-S
各文書のアイデンティティをソートした後、2つの文書を比較します。
出力は、true
質問に提供されたデータ文字列、またはfalse
2つの文書のいずれかが変更された場合です。
次のようにシェルテストで使用できます。
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
終了ステータスがxq
0の場合、終了ステータスは0になります。本物ブール値。
参考までに、問題の2つのファイルに対して内部的に生成された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"
}
]
}
}
]