Claude Codeで流通BMSのXMLを検証する手順 — 必須項目と数量の抜けを一覧化
流通BMSの受発注XMLをClaude Codeにスクリプト化させ、必須項目の抜けと数量・金額の不整合を一覧にする手順です。公式スキーマとの役割分担も扱います。
流通BMSのXMLを読み解く作業は、タグの意味を調べる、必須項目を確かめる、数量と金額を突き合わせるという地味な反復です。Claude Codeには、この反復を検証スクリプトにして実行まで任せられます。ただし、判定の物差しになるのは協議会が配布する仕様です。Claude Codeが作るスクリプトは、その物差しで拾えない業務ルールを補う位置づけになります。
この記事では、受発注メッセージを想定した簡略XMLを題材に、必須項目の抜けと数量・金額の不整合を一覧にするまでを手順化します。実際に手元で動かした出力も載せます。
流通BMSとは何で、XMLのどこを検証するのか
流通BMS(流通ビジネスメッセージ標準)は、消費財流通業界の標準を目指して策定されたEDI標準仕様です。対象は、メッセージ(電子取引文書)と、通信プロトコルおよびセキュリティの2つです。BMSはBusiness Message Standardsの略とされています。
最初の標準メッセージは、2007年4月に「基本形Ver.1.0」として公開されました。ターンアラウンド型取引を前提に、発注、出荷、受領、返品、請求、支払の6業務・8種のメッセージが並びます。その後、軽減税率対応の「基本形Ver2.0」(2018年11月)で請求鑑メッセージが加わりました。2025年4月17日には、値引に関するチェンジリクエストを反映した基本形Ver2.2のXMLスキーマパックの入手申込みが始まっています。
標準メッセージはXML形式で書かれます。データ項目ごとに意味を表すタグが付き、複数の項目をグループ化できるのがXMLの特徴です。固定長のJCA手順では、会社ごとに項目の順番や桁数がばらばらでした。XMLなら、新規の接続先を追加するときもデータの構造をつかみやすくなります。
検証の対象になるのは、大きく次の2層です。
| 層 | 見るもの | 判定の拠り所 |
|---|---|---|
| 構造と属性 | 見るものタグ名、必須要素、繰返し、出現順序、使える文字、桁数、範囲 | 判定の拠り所協議会が提供するXMLスキーマ |
| 業務の整合 | 見るもの数量×単価と金額、行の合計と総額など | 判定の拠り所取引先ごとのマッピングシートと運用ガイドライン |
XMLスキーマが担うのは、構造と属性のほうです。協議会の入門講座の資料も、スキーマの役割を「データ構造(タグ名称、必須要素、不要要素、繰返し、要素の出現順序)」と「データ属性(入力可能データ文字、サイズ・桁数、範囲)」に分けて説明しています。
公式の物差しを先に押さえる
ここで外せない前提があります。XMLスキーマのダウンロードページは、利用登録をした人だけが使えるページです。Claude Codeに「流通BMSの正しいスキーマを書いて」と頼んでも、手元にスキーマが無ければ、それらしい構造を推測で作るだけになります。
そのため、進め方を次のように分けます。
- 構造と属性の検証は、登録して入手した公式スキーマに任せる
- Claude Codeには、スキーマで拾いにくい整合チェックと、結果を一覧にする作業を任せる
- 小売が卸・メーカーに提供するマッピングシートの内容を、検証ルールの根拠にする
マッピングシートは、小売が流通BMSのどの項目をどう使うかを取引先に示す資料です。流通BMS協議会は2016年4月から、希望する小売業のマッピングシートが標準に沿っているかを確認するチェックを運用しています。つまり、項目の使い方は取引先ごとに文書化され、その文書が検証ルールの出どころになります。
仕様の資料は更新されます。2025年5月と7月には、メッセージ項目一覧とマッピングシートの誤記載が訂正されました。値引メッセージだけ「任意」とされていた項目が、全メッセージで「必須」だったため「必須」に直されています。検証ルールを一度書いたら終わりにせず、配布資料の版を記録しておくと、あとで食い違いの原因をたどれます。
検証用の作業フォルダーを用意する
検証用のフォルダーに、サンプルXMLと検証スクリプトを置きます。サンプルは、意図的に問題を2つ仕込んだ発注データです。
bms-lab/
├── CLAUDE.md
├── sample_order.xml
└── check_order.pysample_order.xml は次の内容です。
<?xml version="1.0" encoding="UTF-8"?>
<order>
<orderDate>2012-10-01</orderDate>
<line no="1">
<itemID><name_sbcs>CUPRAMEN</name_sbcs></itemID>
<quantity>50</quantity>
<itemSellingPrice unitPrice="100">5000</itemSellingPrice>
</line>
<line no="2">
<itemID><name_sbcs>SOBA</name_sbcs></itemID>
<quantity>20</quantity>
<itemSellingPrice unitPrice="120">2500</itemSellingPrice>
</line>
<line no="3">
<quantity>10</quantity>
<itemSellingPrice unitPrice="80">800</itemSellingPrice>
</line>
<totalAmount>8300</totalAmount>
</order>仕込んだ問題は2つあります。2行目は、数量20に単価120を掛けると2400になるのに、金額が2500です。3行目は、商品名の要素が丸ごと抜けています。人の目だと3行目の欠落は見つけやすくても、2行目の100円の食い違いは見落としがちです。
CLAUDE.mdに検証の約束事を書く
Claude Codeは、プロジェクトのルートに置いた CLAUDE.md を、セッションの開始時に読みます。コーディング規約や、レビューのチェックリストを書いておく場所です。検証の約束事をここに置くと、依頼のたびに前提を説明し直さずに済みます。
# bms-lab
流通BMSの受発注XMLを検証する作業フォルダー。
## ルール
- XMLの構造と属性の正しさは、協議会配布のXMLスキーマで判定する。
スキーマが手元に無いときは、構造を推測せず、そう報告する。
- スクリプトは標準ライブラリだけで書く(外部パッケージを増やさない)。
- 検査結果は「どの行の、どの項目が、なぜNGか」を1行ずつ出す。
- 検査ルールには、根拠にしたマッピングシートの項番をコメントで残す。
- 実データは扱わない。サンプルは架空の値だけにする。
## 実行
python3 check_order.py sample_order.xml3つ目と4つ目のルールが効きます。出力を「どの行の、どの項目が、なぜ」の形に揃えておけば、結果をそのまま取引先への問い合わせに使えます。根拠の項番をコメントに残すルールは、マッピングシートが訂正されたときの追跡に役立ちます。
Claude Codeに検証スクリプトを書かせる
フォルダーで claude を起動し、次のように依頼します。
sample_order.xml を読んで、次を検査する check_order.py を書いてください。
1. orderDate が無ければ NG
2. 各 line に itemID/name_sbcs、quantity、itemSellingPrice が揃っているか
3. quantity × itemSellingPrice の unitPrice が、金額と一致するか
4. 全行の金額の合計が totalAmount と一致するか
NG は「line 番号: 理由」の1行で出し、最後に件数を出してください。依頼文のポイントは、検査項目に番号を付けて、出力の形まで指定していることです。Claude Codeは、コードベースを読み、ファイルを編集し、コマンドを実行するエージェント型のコーディングツールです。スクリプトを書いて走らせ、結果を見て直すところまでを1回の依頼で続けられます。
生成されたスクリプトの一例が次のものです(手元で動かした版です)。
import sys
import xml.etree.ElementTree as ET
REQUIRED_LINE = ["itemID/name_sbcs", "quantity", "itemSellingPrice"]
def check(path):
root = ET.parse(path).getroot()
problems = []
if root.findtext("orderDate") is None:
problems.append(("header", "orderDate がありません"))
total = 0
for line in root.findall("line"):
no = line.get("no")
for tag in REQUIRED_LINE:
if line.find(tag) is None:
problems.append((f"line {no}", f"必須項目 {tag} がありません"))
qty = line.findtext("quantity")
price = line.find("itemSellingPrice")
if qty and price is not None:
amount = int(price.text)
total += amount
expected = int(qty) * int(price.get("unitPrice"))
if expected != amount:
problems.append((f"line {no}", f"数量×単価={expected} と金額 {amount} が不一致"))
declared = root.findtext("totalAmount")
if declared and int(declared) != total:
problems.append(("footer", f"行金額の合計 {total} と totalAmount {declared} が不一致"))
return problems
if __name__ == "__main__":
found = check(sys.argv[1])
for where, msg in found:
print(f"NG {where}: {msg}")
print(f"{len(found)} 件の問題")
sys.exit(1 if found else 0)実行して、仕込んだ問題が拾えるかを見る
スクリプトを実行します。終了コードも一緒に見ます。
python3 check_order.py sample_order.xml; echo exit=$?Python 3.12で実行した出力は次のとおりです。
NG line 2: 数量×単価=2400 と金額 2500 が不一致
NG line 3: 必須項目 itemID/name_sbcs がありません
2 件の問題
exit=1仕込んだ2件が、そのまま拾えました。3行目の金額800は、数量10と単価80の積と一致しているため、金額の検査は通っています。総額の検査も通りました。行の金額は5000、2500、800で、合計が totalAmount の8300と同じだからです。2行目の金額が誤っていても合計は一致してしまうので、行単位の検査を省くと見逃します。
終了コードが問題の有無で変わる点も大事です。exit=1 を返すスクリプトなら、受信データをバッチで処理する流れの手前に置いて、NGなら止める使い方ができます。
公式スキーマの検証と組み合わせる
Pythonのスクリプトは、業務の整合を見るものです。構造と属性の検証には、入手した公式スキーマを当てます。XMLスキーマ(XSD)の検証は、libxml2に付属する xmllint で実行できます。
xmllint --noout --schema <入手したXSDファイル> sample_order.xml<入手したXSDファイル> は、利用登録のうえダウンロードしたスキーマファイルの名前に置き換えます。簡略XMLはこのスキーマに合わないので、本番に近い形式のデータで試してください。
Claude Codeの役割は、この2つの検証を1本の流れにまとめることです。たとえば次のような依頼ができます。
受信フォルダーの *.xml を順に処理してください。
1. xmllint でスキーマ検証し、失敗したファイルは理由を記録して次へ進む
2. 通ったファイルだけ check_order.py にかける
3. ファイル名、NGの行、理由を1つの CSV にまとめるスキーマ検証の失敗は、構造や桁数、使えない文字の問題です。check_order.py が拾うのは、構造は正しいのに数字が合わないという問題です。原因の種類が違うので、CSVの列も分けておくと、取引先に問い合わせるときに何を聞くかを切り分けやすくなります。
コマンドは対話の外でも使えます。Claude Codeは、ログをパイプで渡したり、CIから呼び出したりできる設計です。検証結果のCSVを claude -p に渡して「NGの理由を取引先向けの問い合わせ文にして」と頼む使い方も、同じ考え方で成り立ちます。
検証ルールを増やすときの注意
ルールを足すほど、検証は便利になる一方で、誤検出も増えます。次の点を押さえておくと、運用が崩れにくくなります。
ルールの根拠を、取引先ごとに持つ。マッピングシートは小売ごとに用意されるため、ある取引先で必須の項目が別の取引先でも必須とは限りません。ルールをコード内の定数にまとめ、取引先名と項番をコメントで残すと、差し替えが楽になります。
金額の丸めと端数を確かめる。簡略XMLでは整数だけで計算しましたが、実際の取引には端数処理があります。数量×単価と金額が1円ずれる原因が、丸めの規則なのか入力ミスなのかは、Claude Codeに判断させず、取引先の運用ガイドラインで決めてください。許容する差を設けるなら、その幅をルールとして明記します。
サンプルは架空の値で作る。実際の取引データには、取引先や価格の情報が含まれます。Claude Codeに読ませる範囲を、架空のサンプルに限る運用が安全です。CLAUDE.md に書いておけば、毎回の依頼で言い直す必要がありません。
配布資料の版を記録する。前述のとおり、メッセージ項目一覧やマッピングシートは訂正されることがあります。検証スクリプトのコメントに、参照した資料の版と日付を残しておくと、のちの食い違いを切り分けられます。
こうした検証ループの組み立て方は、他のデータ形式でも共通です。構造化データをテストで確かめる流れはClaude CodeでJSON-LD構造化データを実装し、テストで検証する手順に、データ変換の影響範囲だけを検証する考え方はClaude Codeでdbt build --selectを回す手順にあります。大量のファイルをテストで確かめる場合は、Claude CodeでPySparkのジョブを書く手順も参考になります。
よくあるつまずき
Claude Codeがスキーマの要素名を推測で書く。公式スキーマを渡していないときに起きやすい現象です。CLAUDE.md に「スキーマが無いときは推測せず報告する」と書き、要素名はスキーマかマッピングシートから引くよう指示します。
数量の単位が混ざる。流通BMSの入門資料のXML例では、quantity に「発注数量(バラ)」の注記が付いています。数量の単位が違う項目を同じ式で掛けると、不整合を誤って報告します。どの項目がどの単位かは、マッピングシートで確かめます。
NGの件数だけを見て安心する。NGが0件でも、検査していない項目は何も保証されていません。検査項目の一覧を CLAUDE.md かREADMEに書いておくと、「通った」の意味が人にも伝わります。
まとめ
流通BMSのXML検証は、構造と属性をスキーマに、業務の整合をスクリプトに分けると整理しやすくなります。Claude Codeに任せやすいのは、後者のスクリプトづくりと、検証結果の一覧化です。公式スキーマの入手とマッピングシートの読み込みは、人が責任を持つ部分として残ります。
最初の一歩は、架空のサンプルを3行ほど作って、仕込んだ問題が拾えるかを確かめることです。拾えたら、取引先のマッピングシートに沿ってルールを1つずつ足していきます。