WSDL ファイルは SOAP サービスの設計図です。クライアントがサービスと通信するために必要な情報 — 利用可能なオペレーション、送信すべきデータ、返ってくるデータ、リクエスト先のアドレス — がすべて定義されています。
問題は、WSDL が非常に読みにくいことです。1つの WSDL が数百行の XML に及び、深くネストされたスキーマ、複数の名前空間、要素間の相互参照が絡み合います。多くの開発者は WSDL を無視して自動生成コードに頼るか、XML を何時間も睨んでサービスの動作を理解しようとしています。
このガイドでは、WSDL を体系的に読む方法を解説します。5 つのコア要素とその接続関係を理解すれば、どんな WSDL でも読み解けるようになります。
WSDL 1.1 の 5 大要素
すべての WSDL 1.1 ドキュメントは、特定の順序で接続された 5 つの要素から構成されています:
┌─────────────────────────────────────────────────┐
│ <wsdl:definitions> │
│ │
│ ┌─────────┐ │
│ │ types │ XSD スキーマ — データ構造の定義 │
│ └────┬────┘ │
│ ↓ │
│ ┌─────────┐ │
│ │ message │ 型付きパーツの名前付きグループ │
│ └────┬────┘ │
│ ↓ │
│ ┌──────────┐ │
│ │ portType │ 抽象的なオペレーション定義 │
│ └────┬─────┘ │
│ ↓ │
│ ┌─────────┐ │
│ │ binding │ 具体的なプロトコル詳細 │
│ └────┬────┘ │
│ ↓ │
│ ┌─────────┐ │
│ │ service │ ネットワークアドレス (エンドポイント) │
│ └─────────┘ │
│ │
└─────────────────────────────────────────────────┘
スタック構造として考えてください。各層は上の層に依存しています。service が「どこに送るか」、binding が「どう送るか」、portType が「何を呼ぶか」、message が「どんなデータを送るか」、types が「データの形」を定義します。
完全な WSDL の例
天気予報サービスの WSDL を使って、各要素を解説します。このサービスには GetCurrentWeather と GetForecast の 2 つのオペレーションがあります。
<?xml version="1.0" encoding="UTF-8"?>
<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"
xmlns:tns="http://example.com/weatherservice"
targetNamespace="http://example.com/weatherservice"
name="WeatherService">
<!-- ==================== -->
<!-- 1. TYPES -->
<!-- ==================== -->
<wsdl:types>
<xsd:schema targetNamespace="http://example.com/weatherservice">
<xsd:element name="GetCurrentWeather">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="countryCode" type="xsd:string"
minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetCurrentWeatherResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="temperature" type="xsd:decimal"/>
<xsd:element name="unit" type="xsd:string"/>
<xsd:element name="condition" type="xsd:string"/>
<xsd:element name="humidity" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetForecast">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="city" type="xsd:string"/>
<xsd:element name="days" type="xsd:int"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetForecastResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="forecasts" type="tns:ForecastDay"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="ForecastDay">
<xsd:sequence>
<xsd:element name="date" type="xsd:date"/>
<xsd:element name="high" type="xsd:decimal"/>
<xsd:element name="low" type="xsd:decimal"/>
<xsd:element name="condition" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<!-- ==================== -->
<!-- 2. MESSAGES -->
<!-- ==================== -->
<wsdl:message name="GetCurrentWeatherRequest">
<wsdl:part name="parameters" element="tns:GetCurrentWeather"/>
</wsdl:message>
<wsdl:message name="GetCurrentWeatherResponse">
<wsdl:part name="parameters"
element="tns:GetCurrentWeatherResponse"/>
</wsdl:message>
<wsdl:message name="GetForecastRequest">
<wsdl:part name="parameters" element="tns:GetForecast"/>
</wsdl:message>
<wsdl:message name="GetForecastResponse">
<wsdl:part name="parameters" element="tns:GetForecastResponse"/>
</wsdl:message>
<!-- ==================== -->
<!-- 3. PORT TYPE -->
<!-- ==================== -->
<wsdl:portType name="WeatherServicePortType">
<wsdl:operation name="GetCurrentWeather">
<wsdl:input message="tns:GetCurrentWeatherRequest"/>
<wsdl:output message="tns:GetCurrentWeatherResponse"/>
</wsdl:operation>
<wsdl:operation name="GetForecast">
<wsdl:input message="tns:GetForecastRequest"/>
<wsdl:output message="tns:GetForecastResponse"/>
</wsdl:operation>
</wsdl:portType>
<!-- ==================== -->
<!-- 4. BINDING -->
<!-- ==================== -->
<wsdl:binding name="WeatherServiceSoapBinding"
type="tns:WeatherServicePortType">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="GetCurrentWeather">
<soap:operation
soapAction="http://example.com/weatherservice/GetCurrentWeather"/>
<wsdl:input><soap:body use="literal"/></wsdl:input>
<wsdl:output><soap:body use="literal"/></wsdl:output>
</wsdl:operation>
<wsdl:operation name="GetForecast">
<soap:operation
soapAction="http://example.com/weatherservice/GetForecast"/>
<wsdl:input><soap:body use="literal"/></wsdl:input>
<wsdl:output><soap:body use="literal"/></wsdl:output>
</wsdl:operation>
</wsdl:binding>
<!-- ==================== -->
<!-- 5. SERVICE -->
<!-- ==================== -->
<wsdl:service name="WeatherService">
<wsdl:port name="WeatherServicePort"
binding="tns:WeatherServiceSoapBinding">
<soap:address location="https://weather.example.com/soap"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
各セクションを詳しく見ていきましょう。
1. Types: データ辞書
<wsdl:types> セクションには、サービスで使用されるすべてのデータ構造を定義する XSD (XML Schema Definition) スキーマが含まれます。TypeScript の interface や JSON Schema に相当する部分です。
主要な XSD の構成要素:
| XSD 構文 | 意味 | 例 |
|---|---|---|
xsd:element | 名前付きデータフィールド | <xsd:element name="city" type="xsd:string"/> |
xsd:complexType | 複数フィールドを持つ構造体 | クラスやインターフェースに相当 |
xsd:sequence | フィールドの出現順序 | 要素の順序付きリスト |
xsd:string | 文字列 | "Tokyo" |
xsd:int | 整数 | 42 |
xsd:decimal | 小数 | 23.5 |
xsd:date | ISO 日付 | 2025-09-19 |
xsd:boolean | 真偽値 | true |
minOccurs="0" | フィールドは省略可能 | 任意項目 |
maxOccurs="unbounded" | フィールドは配列 | 繰り返し要素 |
GetCurrentWeather 要素を読むと、「このオペレーションは必須の city (文字列) と省略可能な countryCode (文字列) を受け取る」ことがわかります。
2. Message: 名前付きパラメータグループ
<wsdl:message> 要素は、型付きパーツを名前付きの単位にグループ化します。各メッセージは types セクションで定義された要素を参照します。
<wsdl:message name="GetCurrentWeatherRequest">
<wsdl:part name="parameters" element="tns:GetCurrentWeather"/>
</wsdl:message>
これは「GetCurrentWeather のリクエストメッセージは、GetCurrentWeather 要素をパラメータとして使用する」という意味です。
document/literal スタイル (最も一般的) では、各メッセージは通常 1 つのパートを持ち、1 つの要素を指します。rpc/encoded スタイル (古い形式) では、複数のパートが明示的な型を持つことがあります。
3. PortType: インターフェース契約
<wsdl:portType> は抽象的なオペレーションを定義します。本質的には API のメソッドシグネチャです。サービスが何をできるかを理解するための最も重要なセクションです。
<wsdl:portType name="WeatherServicePortType">
<wsdl:operation name="GetCurrentWeather">
<wsdl:input message="tns:GetCurrentWeatherRequest"/>
<wsdl:output message="tns:GetCurrentWeatherResponse"/>
</wsdl:operation>
</wsdl:portType>
読み方:「WeatherServicePortType インターフェースには GetCurrentWeather というオペレーションがあり、GetCurrentWeatherRequest メッセージを受け取り、GetCurrentWeatherResponse メッセージを返す」
オペレーションには <wsdl:fault> 要素でエラーレスポンスを定義することもできます。
4. Binding: プロトコルの詳細
<wsdl:binding> は、抽象的なオペレーションを具体的なプロトコルにマッピングする方法を指定します。SOAP サービスでは、SOAP バージョン、エンコーディングスタイル、トランスポートプロトコル、SOAPAction ヘッダーが定義されます。
binding の主要な属性:
| 属性 | 値 | 意味 |
|---|---|---|
style | document または rpc | Body の構造方法 |
transport | http://schemas.xmlsoap.org/soap/http | HTTP トランスポート |
use | literal または encoded | 型のシリアライズ方法 |
soapAction | URI 文字列 | SOAPAction HTTP ヘッダーの値 |
最も一般的な組み合わせは document/literal です。Body にスキーマに正確に一致する XML ドキュメントが含まれます。古いサービスでは rpc/encoded が使われることがあり、パラメータのラッピング方法が異なります。
5. Service: エンドポイントアドレス
<wsdl:service> 要素はすべてを結びつけ、サービスの所在を指定します:
<wsdl:service name="WeatherService">
<wsdl:port name="WeatherServicePort"
binding="tns:WeatherServiceSoapBinding">
<soap:address location="https://weather.example.com/soap"/>
</wsdl:port>
</wsdl:service>
soap:address location が HTTP リクエストの送信先 URL です。1 つのサービスが複数のポート (例: SOAP 1.1 用と SOAP 1.2 用) を持つこともあります。
SOAP 1.1 vs 1.2 の Binding の違い
WSDL が SOAP 1.2 をサポートしている場合、binding セクションで異なる名前空間が使われます:
<!-- SOAP 1.1 -->
<soap:binding xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<!-- SOAP 1.2 -->
<soap12:binding xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
| 項目 | SOAP 1.1 | SOAP 1.2 |
|---|---|---|
| 名前空間 | http://schemas.xmlsoap.org/soap/envelope/ | http://www.w3.org/2003/05/soap-envelope |
| Content-Type | text/xml; charset=utf-8 | application/soap+xml; charset=utf-8 |
| SOAPAction | HTTP ヘッダー | Content-Type の action パラメータ |
| Fault コード | Client、Server | Sender、Receiver |
名前空間の読み方
名前空間は、JSON ベースの API から WSDL に入った開発者にとって最も混乱する部分です。よく見かける名前空間の一覧を示します:
| 接頭辞 | URI | 用途 |
|---|---|---|
wsdl | http://schemas.xmlsoap.org/wsdl/ | WSDL 構造要素 |
soap | http://schemas.xmlsoap.org/wsdl/soap/ | SOAP 1.1 バインディング拡張 |
xsd | http://www.w3.org/2001/XMLSchema | XML Schema 型 |
tns | (サービスごとに異なる) | "This namespace" — サービス自身の名前空間 |
targetNamespace はサービスの一意な識別子です。tns:GetCurrentWeather と記述されている場合、ターゲット名前空間内の GetCurrentWeather 要素を参照しています。
WSDL の読み方: ボトムアップ戦略
WSDL を初めて開いたときは、ボトムアップで読むことをお勧めします:
<wsdl:service>から始める — エンドポイント URL とポート名を確認- binding を辿る — SOAP バージョン、スタイル、SOAPAction 値をチェック
- portType を読む — 利用可能なオペレーションと入出力メッセージを一覧化
- message から types を追跡 — 各オペレーションが期待するデータと返すデータを理解
- XSD の型を調査 — 完全なデータモデルをマッピング
このボトムアップアプローチが効率的な理由は、具体的な情報 (リクエスト送信先) から始めて抽象的な詳細 (データスキーマ) へ向かうためです。
WSDL 調査に役立つツール
| ツール | 種別 | 用途 |
|---|---|---|
| SoapUI | デスクトップアプリ | WSDL の完全なテスト、リクエスト生成 |
| Wizdler | Chrome 拡張機能 | オペレーションの素早い確認 |
| curl | コマンドライン | 生の SOAP リクエストテスト |
| Visual Studio | IDE | WCF クライアント生成 (.NET) |
| wsimport | CLI | Java クライアント生成 |
SoapUI は特に便利です。WSDL をパースして全オペレーションのサンプルリクエストを自動生成するため、すぐに実行可能な出発点を得られます。Qiita や Zenn でも SoapUI の使い方に関する記事が多く、日本語の情報も豊富です。
SOAPless による解決
WSDL を読むスキルは重要ですが、SOAP サービスと連携するたびにそのスキルを発揮する必要はありません。SOAPless は WSDL を自動でパースします。WSDL URL を貼り付けるだけで、すべてのオペレーション、データ型、バインディングが手動の XML 調査なしに抽出されます。
各オペレーションは OpenAPI 3.0 仕様付きの REST エンドポイントに変換されます。メッセージから型を追跡して XML エンベロープを手組みする代わりに、JSON を送って JSON を受け取るだけです。ダッシュボードからオペレーションをインタラクティブにテストできるため、コードを書いたり WSDL を 1 行も読んだりせずに、SOAP サービスの機能を探索できます。
複数の SOAP サービスと連携する必要があるチームにとって、WSDL パース、エンベロープ構築、名前空間デバッグの繰り返しサイクルが不要になります。