ブログ

Mustang で ZUGFeRD を検証する: 何が通り、何が落ちるのか

Mustang は Factur-X / ZUGFeRD の de-facto reference checker です。PDF/A-3 に CII XML を埋め込む際の典型的な failure modes と出荷前検証を解説します。

2026 年にドイツの B2B 顧客へ e-invoice を送るなら、そのファイルは ZUGFeRD-compliant であるか、受領時に bounce されるかのどちらかです。フランスの Factur-X でも同じです。形式は PDF/A-3 wrapper に EN 16931 CII XML を添付したものです。ゼロから生成するのは簡単ではなく、検証には reference engine が必要です。

実務上、その engine は Mustangmustangproject.org)です。PDF/A-3 から embedded XML を抽出し、EN 16931 Schematron に対して validate する open-source Java project です。ZUGFeRD と Factur-X の open-source support は最も深く、多くの independent verifiers が実際に使っています。

この記事では、Mustang が flag する failure modes と、より速く実行する方法を見ます。

Mustang が実際に確認すること

Factur-X または ZUGFeRD PDF を Mustang に渡すと、おおむね次を実行します。

  1. Embedded file を抽出する。PDF/A-3 は attachments を /EmbeddedFiles name tree に保存します。Mustang は canonical filename(Factur-X なら factur-x.xml、ZUGFeRD 2.x なら zugferd-invoice.xml)を探し、bytes を取り出します。
  2. AFRelationship を確認する。Attached file は Factur-X / ZUGFeRD baseline に従って AFRelationship="Alternative" と宣言される必要があります。SourceDataSupplement は fail です。
  3. XMP namespace と version を確認する。Factur-X 1.0 は urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0# を使います。ZUGFeRD 2.x は urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0# を使います。Namespace や version string が違うと fail です。
  4. XML を Cross-Industry Invoice (CII) として parse する。XML は well-formed で、正しい CII root element(rsm:CrossIndustryInvoice)で始まる必要があります。
  5. EN 16931 Schematron を実行する。検証の中心です。field semantics、mandatory codes、totals math、VAT logic、party identifiers など、約 200 の business rules を確認します。

Pass は、EU 内の EN 16931-conformant AP system に受け入れられる invoice であることを意味します。Fail は、顧客の AP automation が受領時に reject し、AR team が manual exception を処理することを意味します。

よく見る 5 つの failure modes

チームが最初の e-invoices をテストすると、validator の Mustang 側によく出ます。

1. Wrong AFRelationship

ERROR: Embedded file factur-x.xml uses AFRelationship="Source",
expected "Alternative".

PDF spec は attached files に複数の relationship types を許可しています。Factur-X / ZUGFeRD は Alternative を要求します。つまり attached XML は visible PDF content の alternative representation です。PDF generator が Data を使う設定(多くの libraries の default)なら、Mustang はすぐ fail します。PDF は表示されても、structured payload は AP system に有効ではありません。

2. Wrong / missing XMP namespace

ERROR: XMP metadata missing fx:DocumentType or fx:DocumentFileName under
namespace urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#.

PDF の XMP packet は、この Factur-X profile(MINIMUMBASICEN 16931EXTENDED)と探すべき filename を宣言する必要があります。PDF/A-3 wrapper を手作業で書くと抜けがちです。gPdf の /api/v1/e-invoice/render endpoint はこれを自動で emit します。

3. CII XML は well-formed だが EN 16931 Schematron が fail

ERROR: BR-CO-25 — In an invoice (BR-01) the
  ram:SpecifiedTradePaymentTerms/ram:DueDateDateTime is required when
  ram:DocumentTypeCode is 380.

実際の failures の大半はこれです。XML の構文は valid ですが、business rules が落ちます。EN 16931 Schematron rules には BR-01BR-CO-25 などの stable IDs があり、仕様で lookup できます。よくあるもの:

  • BR-01: invoice には unique invoice number が必要。
  • BR-04: issue date が必要。
  • BR-05: invoice type code が必要。
  • BR-CO-25: document type が “Commercial invoice” の場合 payment terms が必要。
  • BR-Z-01: VAT category codes は S, Z, E, AE, K, G, O, L, M のいずれか。

Source data を修正し、rebuild して re-validate します。

4. PDF/A wrapper 自体が validate しない

INFO: CII XML extracted and validates against EN 16931.
ERROR: PDF/A-3b conformance check failed: missing Output Intent.

これは Mustang の XML check は pass しているが、underlying PDF/A-3 wrapper が fail しているケースです。よくある原因は、XML は正しくても ordinary PDF を emit していて PDF/A-3 ではないことです。Embedded file はありますが、archival wrapper rules が満たされません。gpdf.com/validator/ は veraPDF を parallel に走らせるため、PDF/A-3 fail は veraPDF column に出て、Mustang は XML pass と表示します。

5. Encoding / declaration mismatch

ERROR: XML declares <?xml version="1.0" encoding="UTF-8"?> but the
embedded byte stream is UTF-8 with BOM. Mustang strict mode rejects BOM.

XML tool が UTF-8 BOM を emit し、それを raw で embed するとよく起きます。対処は embedding 前に BOM を strip することです。gPdf の e-invoice endpoint はこれを normalise します。

Java をインストールせず Mustang を実行する

単発チェックなら Java + Mustang CLI のインストールで構いません。しかし継続的検証、つまり invoice 生成ごと、e-invoice compliance を assert する CI run ごとに使うなら、余計な friction です。

gpdf.com/validator/ は Mustang を browser 内で 実行します。

  1. Factur-X / ZUGFeRD PDF を upload zone に drag します。
  2. Validator が embedded XML を抽出し、Mustang の Schematron engine を実行します(JavaScript / WebAssembly に compiled され、Cloudflare Worker で run)。
  3. Mustang report は veraPDF の PDF/A-3 report と side-by-side で返ります。両方の layer が pass する必要があります。
  4. QA evidence として JSON report を download できます。

Login なし。Quota なし。Maven 経由で入れる Mustang と同じ種類の検証を、無料の public service として提供します。

TL;DR

Mustang は 5 つの common failure modes を flag します。その多くは「fully-conformant Factur-X / ZUGFeRD PDF/A-3 を emit しない tool で生成された」ことに集約されます。gPdf の E-invoice API は一回の call でそれを emit します。validator は Mustang + veraPDF で結果を parallel verify します。

Mustang が捕まえる bugs の多くは wrapper や AFRelationship の問題で、XML semantics だけではありません。File を正しく generate することが大半で、validator はそれを証明する receipt です。