WSDL ファイルをクライアントツールに読み込ませたとき、「Unexpected Element」 や 「Element not expected」 というエラーに遭遇することがあります。このエラーは WSDL のパーサーが XML 構造を正しく解釈できなかったことを意味しますが、根本原因は多岐にわたります。この記事では、代表的な原因と具体的な対処法を解説します。
エラーの典型的な表示
ツールや言語によって表示は異なりますが、以下のようなメッセージが代表的です。
WSDLException: Unexpected element 'types' found at line 12
javax.wsdl.WSDLException: WSDLException (at /wsdl:definitions/wsdl:types):
faultCode=INVALID_WSDL: Unexpected element "{http://schemas.xmlsoap.org/wsdl/}types"
# Python zeep
zeep.exceptions.XMLParseError: Unexpected element 'schema',
expected '{http://schemas.xmlsoap.org/wsdl/}message'
原因 1: 名前空間プレフィックスの不一致
最も一般的な原因です。WSDL のルート要素で宣言した名前空間プレフィックスと、子要素で使われているプレフィックスが一致していないケースです。
<!-- NG: wsdl プレフィックスを宣言していない -->
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<wsdl:types> <!-- wsdl プレフィックスが未定義 -->
...
</wsdl:types>
</definitions>
<!-- OK: プレフィックスが一貫している -->
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<xsd:schema targetNamespace="http://example.com/services">
...
</xsd:schema>
</wsdl:types>
</wsdl:definitions>
対処法: WSDL ファイルの先頭にある definitions 要素の xmlns 宣言を確認し、ドキュメント内で使用されているすべてのプレフィックスが正しく定義されているか検証してください。
原因 2: WSDL 要素の順序違反
WSDL 1.1 の仕様では、definitions 直下の要素は特定の順序で記述することが推奨されています。厳密なパーサーでは順序が異なると Unexpected Element エラーを発生させます。
<!-- 推奨される順序 -->
<wsdl:definitions ...>
<wsdl:types>...</wsdl:types> <!-- 1. 型定義 -->
<wsdl:message>...</wsdl:message> <!-- 2. メッセージ -->
<wsdl:portType>...</wsdl:portType> <!-- 3. ポートタイプ -->
<wsdl:binding>...</wsdl:binding> <!-- 4. バインディング -->
<wsdl:service>...</wsdl:service> <!-- 5. サービス -->
</wsdl:definitions>
対処法: types → message → portType → binding → service の順に並べ替えてください。
原因 3: スキーマインポートの解決失敗
WSDL が外部の XSD ファイルを <xsd:import> や <xsd:include> で参照している場合、そのファイルが取得できないとパースに失敗します。
<wsdl:types>
<xsd:schema>
<!-- この URL にアクセスできないとエラーになる -->
<xsd:import namespace="http://example.com/types"
schemaLocation="https://example.com/types.xsd"/>
</xsd:schema>
</wsdl:types>
確認方法: ブラウザや curl で schemaLocation の URL に直接アクセスして、XSD が取得できるか確認してください。
# スキーマが取得可能か確認
curl -v https://example.com/types.xsd
# WSDL 本体が取得可能か確認
curl -v "https://example.com/service?wsdl"
対処法: 外部スキーマが取得できない場合は、XSD の内容を WSDL ファイル内に直接インライン化するか、ローカルにダウンロードして schemaLocation をローカルパスに変更してください。
原因 4: SOAP バージョンの混在
SOAP 1.1 と SOAP 1.2 では名前空間 URI が異なります。一つの WSDL 内で両方が混在すると、パーサーが混乱します。
<!-- SOAP 1.1 の名前空間 -->
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
<!-- SOAP 1.2 の名前空間 -->
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
対処法: WSDL 内で使用している SOAP バージョンを統一してください。binding 要素の soap:binding がどちらの名前空間を使っているかを確認し、一貫性を保ちましょう。
原因 5: BOM や不可視文字の混入
テキストエディタで WSDL を編集した際に、ファイルの先頭に BOM(Byte Order Mark)が付加されたり、不可視文字が混入することがあります。XML パーサーはこれを予期しない要素として検出します。
# BOM の有無を確認(先頭 3 バイトが EF BB BF なら UTF-8 BOM あり)
hexdump -C service.wsdl | head -1
# BOM を除去
sed -i '1s/^\xEF\xBB\xBF//' service.wsdl
対処法: WSDL ファイルを BOM なし UTF-8 で保存し直してください。
デバッグのワークフロー
Unexpected Element エラーに遭遇したら、以下の手順で調査してください。
- WSDL を XML バリデーターに通す: まず XML として well-formed かを確認する。
- 名前空間の宣言を確認: ルート要素のすべての
xmlns宣言と、ドキュメント内のプレフィックスの整合性を検証する。 - 外部参照の到達性を確認:
importやincludeの URL にアクセスできるかcurlでテストする。 - 別のパーサーで試す: SoapUI、
wsimport(Java)、zeep(Python)など複数のツールで試し、エラーメッセージの差異から原因を絞り込む。 - 最小再現ケースを作る: WSDL を最小限に削り、どの要素を追加するとエラーが再発するか特定する。
WSDL パースの苦労を回避する
WSDL のパースエラーは、XML スキーマの厳密さと各ツールの実装差異が組み合わさって発生する、SOAP 連携特有の問題です。名前空間の不整合、要素順序の違反、外部参照の解決失敗など、原因が多岐にわたるため、デバッグに多大な時間を要します。
SOAPless は WSDL を自動解析して REST API エンドポイントを生成するため、クライアント側で WSDL パーサーと格闘する必要がなくなります。WSDL の URL を指定すれば、約 30 秒で JSON ベースの REST API が利用可能になります。WSDL の複雑さをサービス側に任せ、開発チームはアプリケーション開発に集中できます。