指定定制的模式,以通過 SOAP 綁定公開操作
現在學習如何執行定制的模式與 Data Web Services 生成的模式之間的相互映射。
有指定 XSL 腳本並返回 XML 的操作可以用作 SOAP Web 服務操作。但是,還需要一個定制的模式,該模式通過元素定義描述定制的輸入和輸出消息格式(Data Web Services 不能引用類型定義)。請求消息的限定消息名在 Web 服務中必須是惟一的。本節描述創建一個實際的 SOAP 操作所必須執行的額外步驟。
人力資源部門示例場景
在這個例子中,一家公司的人力資源(HR)部門使用他們定制的模式來跟蹤雇員詳細信息。這個輸入的定制模式被轉換為默認模式,並作為輸入提供給 Web 服務。輸出按默認模式返回,並轉換成定制的輸出模式,如圖 48 所示:
圖 48. HR 場景
創建一個應用到輸入和輸出消息的定制模式。右鍵單擊項目並選擇 New > XML Schema。
圖 49. 創建定制模式
清單 7. NewXMLSchemaInput.xsd - 定制用於輸入消息的 XSD
<?XML version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/HREmpGetInfo" elementFormDefault="qualifIEd">
<element name="HREmpGetInfo">
<complexType>
<sequence>
<element name="EMPSerial" type="xsd:string" nillable="true"/>
</sequence>
</complexType>
</element>
</schema>
清單 8. NewXMLSchemaOutput.xsd - 定制輸出消息的 XSD
<?XML version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/getHREmpDetails" elementFormDefault="qualifIEd">
<element name="getHREmpDetails">
<complexType>
<sequence>
<element name="HREmpPersonalDetails">
<complexType>
<sequence>
<element name="EMP_FIRSTNAME" type="xsd:string"/>
<element name="EMP_MIDINIT" type="xsd:string" nillable="true"/>
<element name="EMP_LastNAME" type="xsd:string"/>
<element name="EMP_SEX" type="xsd:string" nillable="true"/>
<element name="EMP_BDATE" type="xsd:date" nillable="true"/>
</sequence>
</complexType>
</element>
<element name="HREmpSalaryDetails">
<complexType>
<sequence>
<element name="EMP_SERIAL" type="xsd:string"/>
<element name="EMP_YEARLY_COMP" type="xsd:decimal" nillable="true"/>
<element name="EMP_MIDYEAR_BONUS" type="xsd:decimal" nillable="true"/>
<element name="EMP_YEAREND_BONUS" type="xsd:decimal" nillable="true"/>
</sequence>
</complexType>
</element>
<element name="HREmpWorkDetails">
<complexType>
<sequence>
<element name="EMP_DEPT" type="xsd:string" nillable="true"/>
<element name="EMP_WORKNO" type="xsd:string" nillable="true"/>
<element name="EMP_HIREDATE" type="xsd:date" nillable="true"/>
<element name="EMP_JOBDESC" type="xsd:string" nillable="true"/>
<element name="EMP_EDLEVEL" type="xsd:short"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
將定制模式添加到 Web 服務
為了生成正確的 WSDL 文檔,必須提供一個或多個模式,其中包含用於輸入和輸出消息的必要的(定制的)元素定義。要添加一個定制模式,右鍵單擊 Web 服務並選擇 Manage Custom Schemas。
圖 50. 管理定制模式
這時打開 Add or Remove Custom XML Schemas 窗口,可以通過這個窗口管理用於 Web 服務的所有定制模式。單擊 Add 按鈕可以打開另一個窗口,在該窗口中,可以從可被添加到操作中的定制模式中選擇一個目標名稱空間。單擊 Add。
圖 51. 用於管理定制模式的對話框
找到在 清單 7 和 清單 8 中創建的輸入和輸出的定制模式,然後單擊 Open。
圖 52. 選擇默認的模式文件
在添加定制模式之後,可以看到所有添加的模式的目標名稱空間。可以將多個模式添加到 Web 服務,但是所有模式的目標名稱空間必須是惟一的。可以添加與 Web 服務具有相同目標名稱空間的模式。在這種情況下,系統會將定制模式與默認模式合並。這個例子使用兩個模式,一個用於輸入,另一個用於輸出。單擊 Finish。
圖 53. 添加目標名稱空間
模式被添加到項目的 XML Schema 文件夾中。
圖 54. 模式被添加到項目中
創建定制模式與默認模式之間的 XML 映射
現在,必須創建 Web 服務接受的定制模式與默認模式之間的 XML 映射。Data Studio Developer 1.2 提供 XML 映射功能。要創建映射,右鍵單擊項目,並選擇 New > XML Mapping
圖 55. Data Studio 中的 XML 映射功能
選擇項目,將映射命名為 NewMAPInput.map,以便與輸出映射區分開。單擊 Next。
圖 56. 輸入映射文件
現在定義前面創建的定制 XSD 與默認 XSD 文件之間的映射。單擊 Root inputs 域旁邊的 Add 按鈕。
圖 57. 定義映射
浏覽作為輸入提供給默認 XSD 的輸入定制 XSD。
圖 58. 浏覽定制 XSD
選擇輸入定制 XSD 文件,並單擊 OK。
圖 59. 選擇輸入定制 XSD
從 Global elements and types 列表中選擇輸入元素,並單擊 OK。
圖 60. 選擇輸入元素
單擊 Root outputs 域旁邊的 Add:
圖 61. 定義映射
找到前面創建的默認 XSD 文件,並單擊 OK。
圖 62. 定義映射 2
默認 XSD 有兩個元素:一個用於輸入,另一個用於輸出。選擇 getOneEmp 創建用於輸入消息的映射,並單擊 OK。
圖 63. 選擇輸出元素
輸入映射如圖 64 所示。單擊 Finish。
圖 64. 輸入映射
現在,創建定制 XSD 與默認 XSD 之間的真正映射。將鼠標從左邊的表拖動到右邊的表上,創建一個映射,如圖 65 所示。按下 Ctrl+S 保存文件,然後單擊 Generate XSLT script。從主菜單中導航到 Window > Show VIEw > Navigator,然後就可以看到創建的 NewMAPInput.xsl。
圖 65. 創建映射並生成 XSLT 腳本
下面的例子顯示生成的 XSL 文件(NewMAPInput.xsl)。將 清單 7 中顯示的定制 XSD 與這個生成的文件進行比較。可以看到,empno 被映射到 EMPSerial。
清單 9. 通過定制 XSD 與默認 XSD 之間的映射自動生成的 XSL 文件
<?XML version="1.0" encoding="UTF-8"?>
<!-- @generated mapFile="NewMAPInput.map" md5sum="4160833ed98de6b7402c778daaad9541"
version="1.0.120" -->
<!--
*****************************************************************************
* This file has been generated by the IBM XML Mapping Editor V1.0.120
*
* Mapping file: NewMAPInput.map
* Map declaration(s): NewMAPInput
* Input file(s): NewXMLSchemaInput.xsd
* Output file(s):
* DataServerWebServices/MyWebServiceXSLT/MyWebServiceXSLT.getOneEmp.default.xsd
*
* Note: Do not modify the contents of this file as it is overwritten
* each time the mapping model is updated.
*****************************************************************************
-->
<xsl:stylesheet
XMLns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://XML.apache.org/xslt"
XMLns:in="http://www.example.org/HREmpGetInfo"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
XMLns:out="urn:example"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="in xalan"
version="1.0">
<xsl:output method="XML" encoding="UTF-8" indent="yes" xalan:indent-amount="2"/>
<xsl:strip-space elements="*"/>
<!-- root template -->
<xsl:template match="/">
<xsl:apply-templates select="in:HREmpGetInfo" mode="NewMAPInput"/>
</xsl:template>
<!--This rule represents an element mapping: "in:HREmpGetInfo" to "out:getOneEmp".-->
<xsl:template match="in:HREmpGetInfo" mode="NewMAPInput">
<out:getOneEmp>
<!-- a simple data mapping: "in:EMPSerial"(String) to "empno"(String) -->
<empno>
<xsl:value-of select="in:EMPSerial"/>
</empno>
</out:getOneEmp>
</xsl:template>
<!-- ***************** Utility Templates ****************** -->
<!-- copy the namespace declarations from the source to the target -->
<xsl:template name="copyNamespaceDeclarations">
<xsl:param name="root"/>
<xsl:for-each select="$root/namespace::*">
<xsl:copy/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
現在創建輸出映射。為此,右鍵單擊項目並選擇 New > XML Mapping。
圖 66. 創建輸出映射
將映射命名為 NewMAPOutput.map,並單擊 Next。
圖 67. 為輸出映射命名
與前面一樣,單擊 Add,然後找到默認 XSD,因為這一次是將 Web 服務的輸出消息映射到定制模式,然後單擊 OK。
圖 68. 選擇默認 XSD
選擇 getOneEmpResponse,因為現在要創建用於輸出消息的映射。單擊 OK。
圖 69. 選擇輸出元素
再次單擊 Add,並找到定制 XSD,以便將默認輸出消息轉換為定制的輸出消息。單擊 OK。
圖 70. 選擇定制的 XSD 文件
選擇 getHREmpDetails 作為元素,並單擊 OK。
圖 71. 選擇元素
輸出映射應該如圖 72 所示。單擊 Finish。
圖 72. 創建的輸出映射
擴展元素,通過將鼠標從左邊表中的元素拖動到右邊表中的元素,創建默認 XSD 與定制 XSD 之間的一個映射。按下 Ctrl+S 保存文件,然後單擊 Generate XSLT script 工具欄圖標。現在在 Navigator 視圖中可以看到創建的 NewMAPOutput.xsl。
圖 73. 輸出映射
圖 74. 生成的 XSL 文件
下面是生成的 XSL 文件(NewMAPOutput.xsl)。可以花點時間比較一下 清單 8 中的定制 XSD 與生成的文件。
清單 10. 通過定制 XSD 與默認 XSD 之間的映射自動生成的 XSL 文件
<?XML version="1.0" encoding="UTF-8"?>
<!-- @generated mapFile="NewMAPOutput.map" md5sum="6d0669dbb4a79476379126c435e48f52"
version="1.0.120" -->
<!--
*****************************************************************************
* This file has been generated by the IBM XML Mapping Editor V1.0.120
*
* Mapping file: NewMAPOutput.map
* Map declaration(s): NewMAPOutput
* Input file(s):
* DataServerWebServices/MyWebServiceXSLT/MyWebServiceXSLT.getOneEmp.default.xsd
* Output file(s): NewXMLSchemaOutput.xsd
*
* Note: Do not modify the contents of this file as it is overwritten
* each time the mapping model is updated.
*****************************************************************************
-->
<xsl:stylesheet
XMLns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xalan="http://XML.apache.org/xslt"
XMLns:in="urn:example"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
XMLns:out="http://www.example.org/getHREmpDetails"
exclude-result-prefixes="in xalan"
version="1.0">
<xsl:output method="XML" encoding="UTF-8" indent="yes" xalan:indent-amount="2"/>
<xsl:strip-space elements="*"/>
<!-- root template -->
<xsl:template match="/">
<xsl:apply-templates select="in:getOneEmpResponse" mode="NewMAPOutput"/>
</xsl:template>
<!-- This rule represents an element mapping:
"in:getOneEmpResponse" to "out:getHREmpDetails". -->
<xsl:template match="in:getOneEmpResponse" mode="NewMAPOutput">
<out:getHREmpDetails>
<out:HREmpPersonalDetails>
<!-- a simple data mapping:
"row/FIRSTNME"(String) to "out:EMP_FIRSTNAME"(String) -->
<out:EMP_FIRSTNAME>
<xsl:value-of select="row/FIRSTNME"/>
</out:EMP_FIRSTNAME>
<!-- a simple data mapping:
"row/MIDINIT"(String) to "out:EMP_MIDINIT"(String) -->
<out:EMP_MIDINIT>
<xsl:value-of select="row/MIDINIT"/>
</out:EMP_MIDINIT>
<!-- a simple data mapping:
"row/LASTNAME"(String) to "out:EMP_LastNAME"(String) -->
<out:EMP_LastNAME>
<xsl:value-of select="row/LASTNAME"/>
</out:EMP_LastNAME>
<!-- a simple data mapping:
"row/SEX"(String) to "out:EMP_SEX"(String) -->
<out:EMP_SEX>
<xsl:value-of select="row/SEX"/>
</out:EMP_SEX>
<!-- a simple data mapping:
"row/BIRTHDATE"(Date) to "out:EMP_BDATE"(Date) -->
<out:EMP_BDATE>
<xsl:value-of select="row/BIRTHDATE"/>
</out:EMP_BDATE>
</out:HREmpPersonalDetails>
<out:HREmpSalaryDetails>
<!-- a simple data mapping:
"row/EMPNO"(String) to "out:EMP_SERIAL"(String) -->
<out:EMP_SERIAL>
<xsl:value-of select="row/EMPNO"/>
</out:EMP_SERIAL>
<!-- a simple data mapping:
"row/SALARY"(Decimal) to "out:EMP_YEARLY_COMP"(Decimal) -->
<out:EMP_YEARLY_COMP>
<xsl:value-of select="row/SALARY"/>
</out:EMP_YEARLY_COMP>
<!-- a simple data mapping:
"row/BONUS"(Decimal) to "out:EMP_MIDYEAR_BONUS"(Decimal) -->
<out:EMP_MIDYEAR_BONUS>
<xsl:value-of select="row/BONUS"/>
</out:EMP_MIDYEAR_BONUS>
<!-- a simple data mapping:
"row/COMM"(Decimal) to "out:EMP_YEAREND_BONUS"(Decimal) -->
<out:EMP_YEAREND_BONUS>
<xsl:value-of select="row/COMM"/>
</out:EMP_YEAREND_BONUS>
</out:HREmpSalaryDetails>
<out:HREmpWorkDetails>
<!-- a simple data mapping:
"row/WORKDEPT"(String) to "out:EMP_DEPT"(String) -->
<out:EMP_DEPT>
<xsl:value-of select="row/WORKDEPT"/>
</out:EMP_DEPT>
<!-- a simple data mapping:
"row/PHONENO"(String) to "out:EMP_WORKNO"(String) -->
<out:EMP_WORKNO>
<xsl:value-of select="row/PHONENO"/>
</out:EMP_WORKNO>
<!-- a simple data mapping:
"row/HIREDATE"(Date) to "out:EMP_HIREDATE"(Date) -->
<out:EMP_HIREDATE>
<xsl:value-of select="row/HIREDATE"/>
</out:EMP_HIREDATE>
<!-- a simple data mapping:
"row/JOB"(String) to "out:EMP_JOBDESC"(String) -->
<out:EMP_JOBDESC>
<xsl:value-of select="row/JOB"/>
</out:EMP_JOBDESC>
<!-- a simple data mapping:
"row/EDLEVEL"(Short) to "out:EMP_EDLEVEL"(Short) -->
<out:EMP_EDLEVEL>
<xsl:value-of select="row/EDLEVEL"/>
</out:EMP_EDLEVEL>
</out:HREmpWorkDetails>
</out:getHREmpDetails>
</xsl:template>
<!-- ***************** Utility Templates ****************** -->
<!-- copy the namespace declarations from the source to the target -->
<xsl:template name="copyNamespaceDeclarations">
<xsl:param name="root"/>
<xsl:for-each select="$root/namespace::*">
<xsl:copy/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>