XML
XMLは、カスタムタグを入れ子にして構造化データのツリーを表すテキスト形式です。構文、スキーマ、PASCAL VOCアノテーション、JSONやYAMLとの比較について解説します。
XML(拡張可能なマークアップ言語)は、カスタムタグを入れ子にしてツリーを形成する構造化データ用のテキスト形式です。たとえば、<size>要素に<width>と<height>が含まれる形式があります。World Wide Web Consortiumは、ウェブ上でドキュメントやデータを交換するため、SGML(標準一般化マークアップ言語)の簡易サブセットとしてXML 1.0を策定し、1998年2月に勧告として公開しました。HTMLとは異なり、XMLには事前定義されたタグがありません。各アプリケーションがデータの意味を表す独自のタグを定義するため、SVGグラフィックス、RSSフィード、Microsoft Officeドキュメントなど、さまざまなファイル形式がXMLを基盤としています。機械学習やコンピュータービジョンでは、XMLは主にアノテーションファイル、モデルファイル、ならびにトレーニングデータを提供する医療・エンタープライズシステムで使われています。
XMLの構文と検証#
XMLドキュメントのルート要素は1つだけです。要素にはテキスト、子要素、開始タグ内に記述する属性を含めることができます。たとえば<box label="car" xtl="10">のように記述します。また、xmlnsで宣言する名前空間を使って、異なる語彙のタグを区別します。すべてのタグが閉じられ、要素が正しく入れ子になり、属性値が引用符で囲まれているなど、構文規則に従うドキュメントは整形式です。パーサーは整形式性のエラーが最初に見つかった時点で処理を停止する必要があります。ドキュメントは、許可される要素、その順序、データ型を列挙したスキーマにも適合している場合、有効とみなされます。スキーマは文書型定義(DTD)またはXMLスキーマ(XSD)として記述します。size/widthのようなXPath式はツリーからノードを選択し、XSLTスタイルシートはXMLの語彙を別の語彙に変換します。
コンピュータービジョンと機械学習におけるXML#
2005年から2012年まで開催されたPASCAL VOCチャレンジにより、XMLは物体検出で標準的なアノテーション形式となりました。各画像には、ファイル名とサイズ、および物体ごとの<object>要素を記述したXMLファイルが1つあります。この要素にはクラス名、truncatedおよびdifficultフラグ、さらにピクセル単位の角xmin、ymin、xmax、ymaxでバウンディングボックスを定義する<bndbox>が含まれます。アノテーションツールのLabelImgは、デフォルトでこの形式を保存します。そのため、多くのデータセットで今も使われており、データ前処理時に変換が必要です。CVATのCVAT for images 1.1エクスポートでは、タスク内のすべてのアノテーションを1つのXMLファイルに保存し、ボックスはxtl、ytl、xbr、ybrなどの属性で表します。
XMLはモデルやレコードの記述にも使われます。IntelのOpenVINO Intermediate Representationでは、ネットワークの層と接続を.xmlファイルに、重みを対応する.binファイルに保存します。OpenCVの事前学習済みHaarカスケード顔検出器もXML形式で配布されています。臨床AIプロジェクトで画像と組み合わせるHL7 FHIR医療記録は、医用画像解析用にXMLまたはJSONで交換できます。また、WordとExcelのファイルは、文書AIシステムが読み取るXMLパーツを含むZIPアーカイブです。
この例では、Pythonに組み込まれているElementTreeでVOCアノテーションを解析し、各ボックスをYOLOラベル形式の正規化された中心座標、幅、高さに変換します。
import xml.etree.ElementTree as ET
# A PASCAL VOC annotation: one XML file per image, one <object> per box
voc = """
<annotation>
<filename>000017.jpg</filename>
<size><width>480</width><height>364</height><depth>3</depth></size>
<object><name>person</name><difficult>0</difficult>
<bndbox><xmin>185</xmin><ymin>62</ymin><xmax>279</xmax><ymax>199</ymax></bndbox></object>
<object><name>horse</name><difficult>0</difficult>
<bndbox><xmin>90</xmin><ymin>78</ymin><xmax>403</xmax><ymax>336</ymax></bndbox></object>
</annotation>
"""
root = ET.fromstring(voc)
w, h = int(root.find("size/width").text), int(root.find("size/height").text)
# Convert corner pixels to YOLO's normalized center x, center y, width, height
for obj in root.iter("object"):
box = obj.find("bndbox")
x1, y1, x2, y2 = (float(box.find(k).text) for k in ("xmin", "ymin", "xmax", "ymax"))
cx, cy = ((x1 + x2) / 2 - 1) / w, ((y1 + y2) / 2 - 1) / h # VOC pixel indices start at 1
print(obj.find("name").text, f"{cx:.3f} {cy:.3f} {(x2 - x1) / w:.3f} {(y2 - y1) / h:.3f}")このコードはperson 0.481 0.356 0.196 0.376とhorse 0.511 0.566 0.652 0.709を出力します。どちらも画像サイズに対する比率で表した同じ2つのボックスであり、クラスインデックスの後にラベル行として書き込めます。UltralyticsのVOC.yamlデータセットファイルは、初回使用時にこの変換を自動実行します。VOC 2007と2012をダウンロードし、ElementTreeですべてのXMLアノテーションを解析し、difficultとマークされたオブジェクトをスキップして、トレーニング画像16,551枚と検証画像4,952枚分のYOLO .txtラベルを書き込みます。
XML、JSON、YAMLの比較#
- JSON:XMLより簡潔な構文で、オブジェクト、配列、文字列、数値、ブール値を表現します。Pythonの辞書やJavaScriptのオブジェクトにも直接対応します。Web APIとCOCOデータセットのアノテーションで使われています。
- YAML:終了タグの代わりにインデントを使い、コメントにも対応しています。YAML 1.2以降は任意のJSONドキュメントを受け付ける構文で、YOLOのデータセットやモデルのファイルなど、手動編集する設定ファイルで広く使われています。
- XML:スキーマ、名前空間、属性、混在コンテンツ(インラインマークアップを含むテキスト)を備えるため、厳密な検証を必要とするドキュメントや標準化団体に適していますが、より冗長です。
信頼できないXMLの解析#
XMLのエンティティ機能では、ドキュメント内で再利用可能なテキストを定義できますが、攻撃者はこの機能を悪用します。「billion laughs」攻撃では、前の定義をそれぞれ10回参照する約10段階のエンティティ定義によって、数百バイトのファイルが数GBのテキストに展開されます。XML外部エンティティ(XXE)攻撃では、ローカルファイルや内部URLを指すエンティティを宣言するため、脆弱なパーサーはドキュメントに秘密情報を読み込んだり、ネットワーク内部からリクエストを送信したりします。Pythonのxml.etree.ElementTreeは外部エンティティを展開せず、外部エンティティに遭遇すると解析エラーを発生させます。また、付属するExpatパーサーはバージョン2.4.1以降、billion laughs攻撃に耐性があります。defusedxmlパッケージはさらに厳格で、内部・外部を問わず、エンティティ宣言があるとEntitiesForbiddenを発生させます。










