top / index / prev / next / target / source

2005-08-19 diary: Java: WSDL(XMLSchema)パーサ シンプルサンプル

いがぴょんの日記 日記形式でつづる いがぴょんコラム ウェブページです。

old-v2

Java: WSDL(XMLSchema)パーサ シンプルサンプル

Webサービスの WSDL (そしてある箇所はXMLSchema) をパースするシンプルサンプルを作成しました。

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は伝送路上でのデータ品質を保証する機能を持っているようです。初めて知りました。恥を知りました。 httpsは SSLなので TLSの仕様を参照することになります。

暗号化および改ざん防止の機能が、結果として電送路上でのデータ品質低下を防ぐ機能としても働いてくれるのです。まだまだ知らないことが多いです。


この日記について