1. 程式人生 > >WSDL檔案複雜型別的解析及其例項化程式碼生成

WSDL檔案複雜型別的解析及其例項化程式碼生成

1.設計要求

根據WebService的地址,對其WSDL檔案進行解析,重點解析其中包含的複雜型別。針對解析出的複雜型別的結構,生成對應的類例項化程式碼。

2.WSDL解析過程

WSDL的解析過程就是對WSDL內標籤一層一層深入的過程,直到獲得所需的那一層資料,下面以WSDL檔案中的複雜型別(ComplexType)的解析為例,對該部分的程式碼進行說明。

public void parseWSDL(String wsdlURI) throws WSDLException {
    WSDLFactory wsdlFactory = WSDLFactory.newInstance();
        WSDLReader reader = wsdlFactory.newWSDLReader();
        Definition defintion = reader.readWSDL(wsdlURI);//如圖3,根據wsdlURI地址得到的definition即為最外層的標籤
    processTypes(defintion);//如圖4,processTypes函式對defintion下的types標籤進行進一步解析
    }
}

這裡寫圖片描述
圖 3 WSDL檔案層次_definiton
這裡寫圖片描述
圖 4 WSDL檔案層次_types

public void processTypes(Definition defintion) {
    XmlSchemaCollection xmlSchemaCollection = new XmlSchemaCollection();
    Types types = defintion.getTypes();//得到definition下一級中的types
    List list = types.getExtensibilityElements();
    for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
        SchemaImpl schemaImpl = (SchemaImpl) iterator.next();
        Element element = (Element) schemaImpl.getElement();
        XmlSchema xmlSchema = xmlSchemaCollection.read(element);

        XmlSchemaObjectTable smlSchemaObjectTable = xmlSchema.getSchemaTypes();
        //如圖5,得到types下的complexType
        XmlSchemaObjectTable elements = xmlSchema.getElements();
        //如圖5,得到types下的element

        Iterator elementsItr=elements.getValues();//對element進行進一步深入
        while(elementsItr.hasNext()){
            XmlSchemaElement elemt = (XmlSchemaElement) elementsItr.next();
            String elemtName = elemt.getName();
            if(elemtName.equals(CodeGenerate.getBox_function())){
                XmlSchemaType elemtNameType=elemt.getSchemaType();
                search (elemtNameType); //search函式用於對複雜型別進行專門的處理
            }
        }
        Iterator typesItr = smlSchemaObjectTable.getValues();//對complexType進行進一步深入
        while (typesItr.hasNext()) {
            XmlSchemaType type = (XmlSchemaType) typesItr.next();
            String typeName = type.getName();
            if(typeName.equals(complex_type)){
                search(type);
            }
        }
    }
}

這裡寫圖片描述
圖 5 WSDL層次_element and complexType
由於複雜型別的處理比較麻煩,而且複雜型別中可能嵌套了複雜型別,所以單獨寫一個Search函式對WSDL中的複雜型別進行解析處理,由於巢狀關係的存在,程式碼中Search函式中利用了對Search的遞迴呼叫。

public void search(XmlSchemaType type) {
    //如果是複雜型別,則按照XmlSchemaComplexType-> XmlSchemaSequence-> XmlSchemaElement的層次進行解析,因為XmlSchemaElement可能任然是複雜型別,所以需要進一步判斷遞迴呼叫Search。如圖6,圖7
    if (type instanceof XmlSchemaComplexType) {
        XmlSchemaComplexType xmlSchemaComplexType = (XmlSchemaComplexType) type;
        XmlSchemaParticle xmlSchemaParticle = xmlSchemaComplexType.getParticle();
        if (xmlSchemaParticle instanceof XmlSchemaSequence) {
            XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) xmlSchemaParticle;
            XmlSchemaObjectCollection xmlSchemaObjectCollection = xmlSchemaSequence.getItems();
            int count = xmlSchemaObjectCollection.getCount();
            for (int i = 0; i < count; i++) {
                XmlSchemaObject xmlSchemaObject = xmlSchemaObjectCollection.getItem(i);
                if (xmlSchemaObject instanceof XmlSchemaElement) {
                    XmlSchemaElement xmlSchemaElement = (XmlSchemaElement) xmlSchemaObject;
                    String elementName = xmlSchemaElement.getName();
                    XmlSchemaType xmlSchemaType = xmlSchemaElement.getSchemaType();
                    String elementTypeName = xmlSchemaType.getName();
                    if(elementTypeName!=null){
                        value.add(elementName);
                    }
                    search(xmlSchemaType);
                }
            }
        }
        else {//如果這層不是XmlSchemaSequence則直接獲取相應的XmlSchemaAttribute如圖7
            XmlSchemaObjectCollection xmlSchemaObjectCollection=xmlSchemaComplexType.getAttributes();
            int count_att = xmlSchemaObjectCollection.getCount();
            for (int j = 0; j < count_att; j++) {
                XmlSchemaObject xmlSchemaObject = xmlSchemaObjectCollection.getItem(j);
                if (xmlSchemaObject instanceof XmlSchemaAttribute) {
                    XmlSchemaAttribute xmlSchemaAttribute = (XmlSchemaAttribute) xmlSchemaObject;
                    String attributeName = xmlSchemaAttribute.getName();
                    QName xmlSchemaTypename = xmlSchemaAttribute.getSchemaTypeName();
                    String atttype=xmlSchemaTypename.getLocalPart();
                    value.add(attributeName);
                }
            }
        }
    }
}

這裡寫圖片描述
圖 6 WSDL層次_element->complexType->sequence->element
這裡寫圖片描述
圖 7 WSDL層次結構_複雜型別解析

3.WSDLcomplexType解析說明

這裡寫圖片描述
通過對WSDL檔案標籤型別的判斷,採用遞迴的思想,對自定義型別ESBEnvelope進行多層解析,直到得到基本型別的變數如Appcode等。
根據對WSDL的解析可以得到內部定義的類的結構,如圖左邊,對自定義類ESBEnvelope物件的“new以及賦值”相關程式碼的生成過程可以等效成圖右邊,類的結構定義可以等效成樹的結構。

4.自定義類的物件例項化程式碼生成

因此物件例項化的程式碼,可以在WSDL的解析過程中,採用深度優先搜尋演算法(DFS),進行程式碼生成。如下圖
這裡寫圖片描述

5.demo展示及其說明

Step1:如圖2,URL欄目中輸入目標WebService的地址,如(http://172.168.1.134/MyWebService.asmx?wsdl),然後點選getValueFromWSDL按鈕,得到如圖3的介面,此時已經將WebService的方法選項匯入到function下拉列表框中,以及WebService內部可能需要賦值的引數全部匯入到介面中。
Step2:function下拉列表框中選擇需要呼叫的函式;
Value文字框中寫入傳遞引數的名稱;
圖3中 在相應標籤後邊文字框中寫入需要傳遞的引數值,如PassWord右邊空白文字框中填寫 123456;
填寫完畢後,點選Generate,生成所需程式碼,如圖4。
Step3:ctrl+A全選文字編輯區域的文字;
點選copy按鈕或者ctrl+c 對選中文字進行復制
將複製程式碼貼上找Kettle UDJC模組中的程式碼編輯區域。
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述