安全なPythonスクリプトで大きなXMLファイルを素早く分割する

大きな XML ファイルを素早く分割するには、ファイルからバイトを切り取るのではなく、完全な繰り返しレコードで分割します。以下の例では、Python の標準ライブラリを使用して入力をストリーミングし、同じルート要素とルート属性を持つ個別の XML ドキュメントを作成します。これは<records><record>...</record><record>...</record></records>、ルートの直接の子がそれぞれ独立したレコードとなるような、一般的な構造を想定しています。

XMLエディタには、レコードのルート要素が繰り返し表示され、ID、名前、値の子要素を含む拡大されたレコードが表示されます。
ルート直下の繰り返し出現する子レコードで分割します。任意のバイト境界では、XMLマークアップが破損する可能性があります。

安全な分岐点を選択してください

XML文書は1つの文書要素で構成され、そのタグは正しくネストされている必要があります。生のファイル分割ツールは、開始タグ、ネストされたレコード、さらには文字エンコーディングシーケンスを切断してしまう可能性があり、その結果、独立したXMLではない断片が残ってしまうことがあります。W3C XML仕様では、整形式文書とルート要素の規則について説明しています。

分割する前に、ファイルを調べて重複しているレコード要素を特定してください。このスクリプトは、ルート直下のすべての子要素を1つの単位として扱います。子要素が独立したレコードであり、ルート自体に特定の場所に表示する必要のある意味のある混合テキストやメタデータが含まれていない場合にのみ使用してください。レコードが複数階層にネストされている場合は、スクリプトをむやみに変更するのではなく、そのXML語彙用に設計されたスプリッターを使用してください。

Split That XML / OOXP Splitterはどうでしょうか?

元の記事では、読者にSplit That XMLを紹介していました。SourceForgeのプロジェクトページには現在もこのユーティリティの説明がありますが、最終更新日は2015年9月27日となっています。これは旧バージョンのソフトウェアとして扱ってください。古いWindowsとの互換性に関する記述は、現在のシステムでのサポートを保証するものではありません。既にコピーをお持ちの場合は、複製ファイルで作業を行い、出力結果を確認してから使用してください。

Pythonでレコードを分割する

Python はxml.etree.ElementTree.iterparse()ドキュメントを段階的に読み込むため、XML ツリー全体を一度にメモリに読み込む必要がありません。以下のスクリプトは、直接の子要素をバッチにグループ化し、各バッチを元のルート タグと属性の新しいコピー内に書き込みます。サードパーティ パッケージは不要です。Python がインストールされていない場合は、公式のPython for Windows をダウンロードしてください。ここで使用されているパーサーについては、 ElementTree のドキュメントを参照してください。

作業フォルダには、input.xmlとsplit_xml.pyが含まれており、XMLソースはテキストエディタで開かれています。
元のファイルはそのままにしておき、実行ごとに新しい空の出力フォルダを選択してください。
  1. ソース XML の作業コピーを作成します。新しい空の出力フォルダーを作成します (例: ) parts。
  2. プレーンテキストエディタで、以下の内容をsplit_xml.pyコピー元のファイルと同じ作業フォルダに保存してください。
from pathlib import Path
import sys
import xml.etree.ElementTree as ET

source = Path(sys.argv[1])
out_dir = Path(sys.argv[2])
records_per_file = int(sys.argv[3]) if len(sys.argv) > 3 else 500

if records_per_file < 1:
    raise SystemExit("records_per_file must be at least 1")
out_dir.mkdir(parents=True, exist_ok=True)
if any(out_dir.glob("part_*.xml")):
    raise SystemExit("Choose a new, empty output folder first")

records = []
part_count = 0
root = None
root_tag = None
root_attrib = {}

def write_part(items, number):
    wrapper = ET.Element(root_tag, root_attrib)
    wrapper.extend(items)
    target = out_dir / f"part_{number:04d}.xml"
    ET.ElementTree(wrapper).write(
        target, encoding="utf-8", xml_declaration=True
    )

depth = 0
for event, elem in ET.iterparse(source, events=("start", "end")):
    if event == "start":
        depth += 1
        if depth == 1:
            root = elem
            root_tag = elem.tag
            root_attrib = dict(elem.attrib)
    else:
        if depth == 2:
            records.append(elem)
            if len(records) == records_per_file:
                part_count += 1
                write_part(records, part_count)
                records.clear()
                root[:] = []
        depth -= 1

if records:
    part_count += 1
    write_part(records, part_count)
if part_count == 0:
    raise SystemExit("No direct-child elements were found under the root")
print(f"Wrote {part_count} files.")

コマンドを実行してください

作業フォルダーでPowerShellを開き、Pythonが利用可能であることを確認してください。最後の引数は、パートごとのレコード数です。省略した場合のデフォルト値は500です。

python --version
python split_xml.py input.xml parts 500

Python ランチャーを使用する Windows 環境では、2 行目は となりますpy -3 split_xml.py input.xml parts 500。スクリプトは などのファイルを書き込みpart_0001.xml、作成したファイルの数を報告します。毎回空のアウトプット フォルダーを使用してください。一致するパーツ ファイルが既に存在する場合、スクリプトは停止するため、新しい実行が残余ファイルと混ざってしまうことはありません。

Windows PowerShellウィンドウに、input.xmlを500レコードずつに分割するコマンドが表示されます。
3番目のコマンド引数はレコード数を設定するものであり、保証された最大ファイルサイズを設定するものではありません。

インポートする前に結果を確認してください

まず、生成された各部分を解析して、不正な形式のXMLを検出します。PowerShellから、以下を実行します。

python -c "import glob, xml.etree.ElementTree as ET; files=glob.glob('parts/*.xml'); [ET.parse(p) for p in files]; print(f'{len(files)} files parsed')"

報告された数値がゼロでないことを確認し、いくつかのファイルを検査して、レコードの総数をソースと比較してください。解析が成功したとしても、それはパートが整形式であることを証明するだけです。XMLスキーマ(XSD)、DTD、ビジネスルール、またはそれを利用するアプリケーションの要件を満たしていることを証明するものではありません。それが重要な場合は、宛先システムで使用されるスキーマまたはバリデータを使用して各パートを検証してください。W3C XMLスキーマのリソースでは、スキーマ制約の個別の役割について説明しています。

パーツフォルダには、出力結果を確認するためのコマンドプロンプトの上に、3つのXMLパーツファイルが一覧表示されます。
各部分を解析して整形式性を確認した後、アプリケーションのスキーマチェックまたはインポートチェックを個別に実行します。

制限事項と応急処置

  • パートのサイズがまだ大きすぎます。レコード数を減らしてください(例えば、500から100に)。大きなレコードが1つあるだけで、パートのサイズが目標サイズを超える場合があります。このスクリプトは厳密なメガバイトの上限を設けていません。
  • パーツがスキーマ検証に失敗しました。選択したレコード境界がスキーマの要求される構造と順序と一致していることを確認してください。分割によって、文書レベルの妥当性を維持せずに、整形式のネスト構造を維持できる場合があります。
  • プレフィックスまたはフォーマットが変更されています。ElementTreeは名前空間プレフィックスを異なる方法でシリアル化し、XML 表現を正規化する場合があります。バイト単位のコピーを期待するのではなく、解析された値とアプリケーションの動作を比較してください。
  • ソースコードはDTD、コメント、処理命令、またはルートレベルのメタデータを使用しています。この単純なスクリプトでは、ドキュメントレベルのすべての構造が保持されるわけではありません。代わりに、語彙対応のXMLツールを使用してコピーでテストしてください。

独立したレコードの通常のリストの場合、このアプローチでは、親子関係のマークアップを損なうことなく、管理しやすく個別に解析可能なファイルを作成できます。レコード構造と宛先の検証ルールによって、結果として得られる部分がワークフローに対しても有効かどうかが決まります。

コメントを残す

FotoSketcherで写真を絵画、スケッチ、漫画に変換

FotoSketcherで写真を絵画、スケッチ、漫画に変換

FotoSketcher Studioを使えば、写真を絵画、鉛筆画、漫画に変換できます。エフェクトの選択方法、プレビューの調整方法、作品の保存方法を学びましょう。

オーディオ識別ツールで音声ファイルを詳細に分析・識別する

オーディオ識別ツールで音声ファイルを詳細に分析・識別する

オーディオ識別子がビットレート、エンコーダー、タグについて何を明らかにするのか、従来のワークフローがどのように機能するのか、そして現在利用可能なツールの中で、ファイルの検査や楽曲の識別に使えるものはどれなのかを学びましょう。

My Photo Index:Windows用オープンソース写真整理ツール

My Photo Index:Windows用オープンソース写真整理ツール

My Photo Indexは、ローカル画像のタグ付け、評価、閲覧を行うための、Windows向けの旧来の写真カタログツールです。その機能、互換性の制限、および現在もサポートされている代替ツールについてご確認ください。

Attribute Changerを使用してファイルとフォルダの属性、日付、時刻を変更する

Attribute Changerを使用してファイルとフォルダの属性、日付、時刻を変更する

Attribute Changerを使用して、Windowsファイルの属性とタイムスタンプを編集したり、JPEG EXIF写真の日付を更新したり、バッチ変更を安全にプレビューしたりする方法を学びましょう。

Windows 10で各モニターに異なる壁紙を設定する方法

Windows 10で各モニターに異なる壁紙を設定する方法

Windows 10の各モニターに個別の壁紙を設定し、ディスプレイを識別し、画像のフィットを調整し、モニターの選択肢が見つからない場合のトラブルシューティングを行います。

pViewer:最小限の画像ビューアとマンガ&コミックリーダー

pViewer:最小限の画像ビューアとマンガ&コミックリーダー

pViewerの機能、写真モードとコミックモードの仕組み、ダウンロードすべきWindows版、そして旧バージョンと改訂版の違いについて学びましょう。

NeoDownloader:パラメータ設定とウェブサイトからの画像の一括ダウンロード

NeoDownloader:パラメータ設定とウェブサイトからの画像の一括ダウンロード

NeoDownloaderプロジェクトの作成方法、クロール範囲の選択方法、画像フィルタと保存先の設定方法、バッチダウンロードの確認方法を学びましょう。

Windows 7および8でホットキーを使って次のデスクトップ背景に切り替える方法

Windows 7および8でホットキーを使って次のデスクトップ背景に切り替える方法

Windows 7または8用のスライドショーを設定し、簡単なVBScriptショートカットを作成して、キーボードショートカットキーを割り当てて次の壁紙に進めるようにします。

XnConvert:エフェクトの適用と画像フォーマットの一括変換

XnConvert:エフェクトの適用と画像フォーマットの一括変換

XnConvertを使えば、エフェクトの適用、写真のリサイズ、画像フォーマットの一括変換が可能です。出力設定の選択、編集内容のプレビュー、オリジナル画像の保護も行えます。

PickMeApp: 保存された設定でWindowsプログラムを転送する

PickMeApp: 保存された設定でWindowsプログラムを転送する

PickMeAppを使って、インストール済みのWindowsアプリケーションを別のPCに移行しましょう。TAPパッケージの仕組み、設定の取得方法、転送できない可能性のある項目について学びます。