top / index / prev / next / target / source
日記形式でつづる いがぴょんコラム ウェブページです。
Webサービスの WSDL (そしてある箇所はXMLSchema) をパースするシンプルサンプルを作成しました。
WSDL (XMLSchema) を解析するシンプルなサンプルを作成しました。 入力として試したwsdlファイル
<?xml version="1.0" encoding="UTF-8"?><wsdl:definitions
targetNamespace="http://localhost:8080/axis/WsTest02.jws"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="http://localhost:8080/axis/WsTest02.jws"
xmlns:intf="http://localhost:8080/axis/WsTest02.jws"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns1="http://MyNamespace"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<wsdl:types>
<schema
targetNamespace="http://MyNamespace"
xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://localhost:8080/axis/WsTest02.jws"/>
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="WsTestInput">
<sequence>
<element name="arg1" type="xsd:int"/>
<element name="arg2" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<complexType name="WsTestOutput">
<sequence>
<element name="arg3" type="xsd:int"/>
<element name="arg4" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
</schema>
<schema
targetNamespace="http://localhost:8080/axis/WsTest02.jws"
xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://MyNamespace"/>
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="ArrayOfWsTestInput">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="tns1:WsTestInput[]"/>
</restriction>
</complexContent>
</complexType>
<complexType name="ArrayOfWsTestOutput">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="tns1:WsTestOutput[]"/>
</restriction>
</complexContent>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="method02Request">
<wsdl:part name="input" type="impl:ArrayOfWsTestInput"/>
</wsdl:message>
<wsdl:message name="method01Response">
<wsdl:part name="method01Return" type="xsd:string"/>
</wsdl:message>
<wsdl:message name="method01Request">
<wsdl:part name="arg1" type="xsd:string"/>
<wsdl:part name="arg2" type="xsd:int"/>
</wsdl:message>
<wsdl:message name="method02Response">
<wsdl:part name="method02Return" type="impl:ArrayOfWsTestOutput"/>
</wsdl:message>
<wsdl:portType name="WsTest02">
<wsdl:operation name="method01" parameterOrder="arg1 arg2">
<wsdl:input message="impl:method01Request" name="method01Request"/>
<wsdl:output message="impl:method01Response" name="method01Response"/>
</wsdl:operation>
<wsdl:operation name="method02" parameterOrder="input">
<wsdl:input message="impl:method02Request" name="method02Request"/>
<wsdl:output message="impl:method02Response" name="method02Response"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="WsTest02SoapBinding" type="impl:WsTest02">
<wsdlsoap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="method01">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="method01Request">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://MyNamespace"
use="encoded"/>
</wsdl:input>
<wsdl:output name="method01Response">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://localhost:8080/axis/WsTest02.jws"
use="encoded"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="method02">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="method02Request">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://MyNamespace"
use="encoded"/>
</wsdl:input>
<wsdl:output name="method02Response">
<wsdlsoap:body
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="http://localhost:8080/axis/WsTest02.jws"
use="encoded"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="WsTest02Service">
<wsdl:port binding="impl:WsTest02SoapBinding" name="WsTest02">
<wsdlsoap:address location="http://localhost:8080/axis/WsTest02.jws"/>
</wsdl:port>
</wsdl:service></wsdl:definitions>
このWSDLをパースするのに とりあえず2パスで考えました。
まずは XMLSchemaの解析です。 WsdlSchemaSimpleParser.java
/*
* WSDLスキーマのシンプルなパーササンプル
* Copyright (C) 2005 いがぴょん
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* WSDLスキーマのシンプルなパーササンプルです。
*
* @author Tosiki Iga
*/
public class WsdlSchemaSimpleParser {
private Element elementDefinitions;
public static void main(String[] args) {
new WsdlSchemaSimpleParser().process();
}
public void process() {
DOMResult domResult = new DOMResult();
try {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(new StreamSource(new FileInputStream(
"./dat/test.wsdl")), domResult);
} catch (TransformerConfigurationException e) {
e.printStackTrace();
return;
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
} catch (TransformerException e) {
e.printStackTrace();
return;
}
Node nodeRoot = domResult.getNode().getFirstChild();
if (nodeRoot == null || nodeRoot instanceof Element == false) {
System.out.println("ルートノードが見つかりません.");
return;
}
elementDefinitions = (Element) nodeRoot;
NodeList listTypes = elementDefinitions.getElementsByTagNameNS(
"http://schemas.xmlsoap.org/wsdl/", "types");
if (listTypes == null || listTypes.item(0) instanceof Element == false) {
System.out.println("スキーマ定義(types)が見つかりません。処理スキップします。");
} else {
Element elementTypes = (Element) listTypes.item(0);
System.out.println("スキーマ定義(types)を解釈開始します。");
NodeList listSchema = elementTypes.getElementsByTagNameNS(
"http://www.w3.org/2001/XMLSchema", "schema");
for (int index = 0; index < listSchema.getLength(); index++) {
Element elementSchema = (Element) listSchema.item(index);
System.out.println("名前空間["
+ elementSchema.getAttribute("targetNamespace")
+ "]の定義が始まります。");
NodeList listComplexType = elementSchema
.getElementsByTagName("complexType");
for (int indexComplexType = 0; indexComplexType < listComplexType
.getLength(); indexComplexType++) {
Element elementComplexType = (Element) listComplexType
.item(indexComplexType);
System.out.println(" コンプレックス型["
+ elementComplexType.getAttribute("name") + "]");
// sequenceのあるものかどうか
processSequence(elementComplexType);
// complexContentがあるかどうか
processComplexContent(elementComplexType);
}
}
}
}
private void processSequence(Element elementComplexType) {
NodeList listSequence = elementComplexType
.getElementsByTagName("sequence");
if (listSequence.getLength() != 0) {
for (int indexSequence = 0; indexSequence < listSequence
.getLength(); indexSequence++) {
Element elementSequence = (Element) listSequence
.item(indexSequence);
NodeList listElement = elementSequence
.getElementsByTagName("element");
for (int indexElement = 0; indexElement < listElement
.getLength(); indexElement++) {
Element elementElement = (Element) listElement
.item(indexElement);
System.out.println(" エレメント(element)が開始されます。");
System.out.println(" 名前["
+ elementElement.getAttribute("name") + "]");
System.out.println(" 型 ["
+ elementElement.getAttribute("type") + "]");
System.out.println(" NULL許容["
+ ("true".equals(elementElement
.getAttribute("nillable")) ? "true"
: "false") + "]");
}
}
}
}
private void processComplexContent(Element elementComplexType) {
NodeList listComplexContent = elementComplexType
.getElementsByTagName("complexContent");
if (listComplexContent.getLength() != 0) {
for (int indexComplexContent = 0; indexComplexContent < listComplexContent
.getLength(); indexComplexContent++) {
Element elementComplexContent = (Element) listComplexContent
.item(indexComplexContent);
NodeList listRestriction = elementComplexContent
.getElementsByTagName("restriction");
for (int indexRestriction = 0; indexRestriction < listRestriction
.getLength(); indexRestriction++) {
Element elementRestriction = (Element) listRestriction
.item(indexRestriction);
System.out.println(" restrictionが開始されます。");
System.out.println(" base["
+ elementRestriction.getAttribute("base")
+ "] ※現状では [soapenc:Array] しか想定しません。");
NodeList listAttrubute = elementRestriction
.getElementsByTagName("attribute");
for (int indexAttrubute = 0; indexAttrubute < listAttrubute
.getLength(); indexAttrubute++) {
Element elementAttrubute = (Element) listAttrubute
.item(indexAttrubute);
System.out.println(" ref["
+ elementAttrubute.getAttribute("ref") + "]");
String wsdl_arrayType = elementAttrubute
.getAttribute("wsdl:arrayType");
System.out.println(" wsdl:arrayType["
+ wsdl_arrayType + "]");
String arrayTypeNS = null;
String arrayTypeValue = wsdl_arrayType;
if (wsdl_arrayType.indexOf(":") > 0) {
// 名前空間指定付きの型が参照されています。
arrayTypeNS = wsdl_arrayType.substring(0,
wsdl_arrayType.indexOf(":"));
arrayTypeValue = wsdl_arrayType
.substring(wsdl_arrayType.indexOf(":") + 1);
}
System.out.println(" 利用している型は[" + arrayTypeValue
+ "]");
if (arrayTypeNS != null) {
System.out.println(" その型は名前空間["
+ elementDefinitions.getAttribute("xmlns:"
+ arrayTypeNS) + "]の中にあります。");
}
}
}
}
}
}
}
続いて Webサービスの定義を読み込むサンプルです。 WsdlServiceSimpleParser.java
/*
* WSDLサービスのシンプルなパーササンプル
* Copyright (C) 2005 いがぴょん
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* WSDLサービスのシンプルなパーササンプルです。
*
* @author Tosiki Iga
*/
public class WsdlServiceSimpleParser {
private Element elementDefinitions;
public static void main(String[] args) {
new WsdlServiceSimpleParser().process();
}
public void process() {
DOMResult domResult = new DOMResult();
try {
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(new StreamSource(new FileInputStream(
"./dat/test.wsdl")), domResult);
} catch (TransformerConfigurationException e) {
e.printStackTrace();
return;
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
} catch (TransformerException e) {
e.printStackTrace();
return;
}
Node nodeRoot = domResult.getNode().getFirstChild();
if (nodeRoot == null || nodeRoot instanceof Element == false) {
System.out.println("ルートノードが見つかりません.");
return;
}
elementDefinitions = (Element) nodeRoot;
NodeList listService = elementDefinitions
.getElementsByTagName("wsdl:service");
if (listService == null
|| listService.item(0) instanceof Element == false) {
System.out.println("サービス定義(wsdl:service)が見つかりません。処理スキップします。");
} else {
Element elementService = (Element) listService.item(0);
System.out.println("サービス定義(wsdl:service)を解釈開始します。");
NodeList listPort = elementService
.getElementsByTagName("wsdl:port");
for (int index = 0; index < listPort.getLength(); index++) {
Element elementPort = (Element) listPort.item(index);
String portName = elementPort.getAttribute("name");
String binding = elementPort.getAttribute("binding");
System.out.println("ポート[" + portName + "]の定義が始まります。");
System.out.println(" binding[" + binding + "]");
NodeList listAddress = elementPort
.getElementsByTagName("wsdlsoap:address");
for (int indexAddress = 0; indexAddress < listAddress
.getLength(); indexAddress++) {
Element elementAddress = (Element) listAddress
.item(indexAddress);
System.out.println(" アドレス["
+ elementAddress.getAttribute("location") + "]");
// PortTypeを解釈します。
if (processPortType(elementPort, portName) == false) {
System.out.println("portType[" + portName
+ "]を処理することができませんでした。");
return;
}
System.out.println("");
System.out.println("※このプログラムは bindingを無視してしまっています。");
// bindingを解釈します。
if (processBinding(elementPort, binding) == false) {
System.out.println("binding[" + binding
+ "]を処理することができませんでした。");
return;
}
}
}
}
}
/**
* portTypeを解釈します。
*
* @param elementPort
* @param portName
* @return
*/
private boolean processPortType(Element elementPort, String portName) {
NodeList listPortType = elementDefinitions
.getElementsByTagName("wsdl:portType");
for (int indexPortType = 0; indexPortType < listPortType.getLength(); indexPortType++) {
Element elementPortType = (Element) listPortType
.item(indexPortType);
if (elementPort.getAttribute("name").equals(portName)) {
System.out.println("portType["
+ elementPortType.getAttribute("name") + "]を処理します。");
NodeList listOperation = elementPortType
.getElementsByTagName("wsdl:operation");
for (int indexOperation = 0; indexOperation < listOperation
.getLength(); indexOperation++) {
Element elementOperation = (Element) listOperation
.item(indexOperation);
System.out.println("オペレーション(operation)["
+ elementOperation.getAttribute("name")
+ "]が開始します。");
System.out.println(" パラメータ順序["
+ elementOperation.getAttribute("parameterOrder")
+ "] ※パラメータ順序は とりあえず無視します。");
NodeList listInput = elementOperation
.getElementsByTagName("wsdl:input");
if (listInput.getLength() != 0) {
Element elementInput = (Element) listInput.item(0);
System.out.println(" 入力:name["
+ elementInput.getAttribute("name") + "]");
if (processMessage(elementInput.getAttribute("message")) == false) {
System.out.println("message["
+ elementInput.getAttribute("message")
+ "]を処理することができませんでした。");
return false;
}
}
NodeList listOutput = elementOperation
.getElementsByTagName("wsdl:output");
if (listOutput.getLength() != 0) {
Element elementOutput = (Element) listOutput.item(0);
System.out.println(" 出力:name["
+ elementOutput.getAttribute("name") + "]");
if (processMessage(elementOutput
.getAttribute("message")) == false) {
System.out.println("message["
+ elementOutput.getAttribute("message")
+ "]を処理することができませんでした。");
return false;
}
}
}
return true;
}
}
return false;
}
/**
* メッセージ(message)を解釈します。
*
* @param messageName
*/
private boolean processMessage(String messageName) {
String messageNS = null;
String messageValue = messageName;
System.out.println(" メッセージ:message[" + messageName + "]");
if (messageValue.indexOf(":") > 0) {
// 名前空間指定付きの型が参照されています。
messageNS = messageValue.substring(0, messageValue.indexOf(":"));
messageValue = messageValue
.substring(messageValue.indexOf(":") + 1);
}
System.out.println(" 利用している型は[" + messageValue + "]");
if (messageNS != null) {
System.out.println(" その型は名前空間["
+ elementDefinitions.getAttribute("xmlns:" + messageNS)
+ "]の中にあります。");
}
NodeList listMessage = elementDefinitions
.getElementsByTagName("wsdl:message");
for (int indexMessage = 0; indexMessage < listMessage.getLength(); indexMessage++) {
Element elementMessage = (Element) listMessage.item(indexMessage);
if (elementMessage.getAttribute("name").equals(messageValue)) {
NodeList listPart = elementMessage
.getElementsByTagName("wsdl:part");
for (int indexPart = 0; indexPart < listPart.getLength(); indexPart++) {
Element elementPart = (Element) listPart.item(indexPart);
System.out.println(" 変数名["
+ elementPart.getAttribute("name") + "] 型["
+ elementPart.getAttribute("type") + "]");
}
return true;
}
}
return false;
}
/**
* 基本的に bindingは読み飛ばすこととします。
*
* @param elementPort
* @param binding
* @return
*/
private boolean processBinding(Element elementPort, String binding) {
if (binding.indexOf(":") > 0) {
binding = binding.substring(binding.indexOf(":") + 1);
}
NodeList listBinding = elementDefinitions
.getElementsByTagName("wsdl:binding");
for (int indexBinding = 0; indexBinding < listBinding.getLength(); indexBinding++) {
Element elementBinding = (Element) listBinding.item(indexBinding);
if (elementBinding.getAttribute("name").equals(binding)) {
System.out.println("binding["
+ elementBinding.getAttribute("name") + "]を処理します。");
System.out.println(" type["
+ elementBinding.getAttribute("type") + "]");
NodeList listOperation = elementBinding
.getElementsByTagName("wsdl:operation");
for (int indexOperation = 0; indexOperation < listOperation
.getLength(); indexOperation++) {
Element elementOperation = (Element) listOperation
.item(indexOperation);
System.out.println("オペレーション(operation)["
+ elementOperation.getAttribute("name")
+ "]が開始します。");
NodeList listInput = elementOperation
.getElementsByTagName("wsdl:input");
if (listInput.getLength() != 0) {
Element elementInput = (Element) listInput.item(0);
System.out.println(" 入力:name["
+ elementInput.getAttribute("name") + "]");
}
NodeList listOutput = elementOperation
.getElementsByTagName("wsdl:output");
if (listOutput.getLength() != 0) {
Element elementOutput = (Element) listOutput.item(0);
System.out.println(" 出力:name["
+ elementOutput.getAttribute("name") + "]");
}
}
return true;
}
}
return false;
}
}
関連する日記
httpsは伝送路上でのデータ品質を保証する機能を持っているようです。初めて知りました。恥を知りました。 httpsは SSLなので TLSの仕様を参照することになります。
暗号化および改ざん防止の機能が、結果として電送路上でのデータ品質低下を防ぐ機能としても働いてくれるのです。まだまだ知らないことが多いです。