12,000を超えるXMLファイルを解析しました。

12,000を超えるXMLファイルを解析しました。

12,000を超えるXMLファイルを含むフォルダがあります。このフォルダから特定の基準を満たすファイルのリストをインポートする必要があります。

XMLファイルにはというノードがあります/BillingData/InvoiceLinesList/InvoiceLinesInvoiceLines1つ以上がある可能性がありますInvoiceLinesList。で値のあるInvoiceLinesタグを検索する必要があり<charge>、名前付きの同じ99タグ内に値があるタグがあります。InvoiceLines<chargeType>D

最良のアプローチは何ですか?を使うとawkこんなに可能かもしれないと思っていましたが、うまくいかないので、複数の基準で検索する方法が見つかりませんawk。ここでは潜在的なアプローチを見ることができますが、xmlstarlet複数のタグで別々の値を見つけるのではなく、単一のタグで1つまたは別の値だけを探します。

ベストアンサー1

通常、XML(およびJSONやYAMLなどの他の同様の形式)awkを解析するのには適していません。sedたとえば、この XML 例では、ノードが保存される順序または改行InvoiceLinesで区切られているかどうかはわかりません。 XML形式はこれらのことを気にしませんが、可能な限り(データ内のすべての可能なエンコーディングを含む)処理に特別な注意を払わない限り、awkORスクリプトは簡単に失敗する可能性があります。sedどのデバイスに関係なく解析されます。

したがって、XMLパーサー(組み込みパーサーなどxmlstarlet)を使用することは正しいアプローチです。


次のコマンドは、ファイルに1つ以上の必須ノードが見つかると、入力ファイルのファイル名を印刷しますfile.xml。複数のInvoiceLinesノードが一致する場合、ファイル名は、間に改行を含む複数回印刷されます。これは、最初から改行文字を含むファイル名を抑制することを意味します。

xmlstarlet sel \
    -t -m '/BillingData/InvoiceLinesList/InvoiceLines[chargeType = "D" and charge = "99"]' \
    --inp-name -nl file.xml

XPATHクエリは、指定された値を持つ子ノードを持つすべてのInvoiceLinesノードと一致します。 1つをテストする代わりに使用chargeTypecharge@chargechargecharge プロパティInvoiceLinesところで、ノードから。

単一ディレクトリ内のすべてのXMLファイルに適用します。

xmlstarlet sel \
    -t -m '/BillingData/InvoiceLinesList/InvoiceLines[chargeType = "D" and charge = "99"]' \
    --inp-name -nl ./*.xml

ファイルが多すぎて上記でエラーが発生した場合は、次のものを使用できますxargs

printf '%s\n' ./*.xml | xargs xmlstarlet -t -m ...

またはfind(サブディレクトリも検索します):

find . -type f -name '*.xml' -exec xmlstarlet -t -m ... {} +

uniqファイルのリストを一意にするには、結果をパイプします。


上記をテストするために、次のXMLを使用しました。

<BillingData>
    <InvoiceLinesList>
        <InvoiceLines>
            <chargeType>D</chargeType>
            <charge>99</charge>
        </InvoiceLines>
        <InvoiceLines>
            <chargeType>D</chargeType>
            <charge>99</charge>
        </InvoiceLines>
        <InvoiceLines>
            <chargeType>E</chargeType>
            <charge>99</charge>
        </InvoiceLines>
    </InvoiceLinesList>
</BillingData>

おすすめ記事