我有一个用于定义模式的wsdl:
<xsd:schema elementFormDefault="unqualified"
targetNamespace="http://www.xpto.com/xpto">
和元素:
<xsd:element name="insertResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="sys_id"
type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="table"
type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="display_name"
type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="display_value"
type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="1" name="status"
type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="0" name="status_message"
type="xsd:string"/>
<xsd:element maxOccurs="1" minOccurs="0" name="error_message"
type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
但是当我执行操作并获得响应时,SoapUI说它无效:
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Body>
<insertResponse xmlns="http://www.xpto.com/xpto">
<sys_id>something</sys_id>
<table>something</table>
<display_name>number</display_name>
<display_value>something</display_value>
<status>something</status>
</insertResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
SoapUI消息(包含易读性的行):
line 4: Expected element 'sys_id' instead of
'sys_id@http://www.xpto.com/xpto' here in element
insertResponse@http://www.xpto.com/xpto
如果我将WSDL更改为包含elementFormDefault="qualified"
,则在架构中,相同的响应有效。
为什么没有elementFormDefault="qualified"
这个回复无效,这是正确的做法?
此WSDL生成的代码也不喜欢响应,但失败了:
Unmarshalling Error: unexpected element
(uri:\\"http://www.xpto.com/xpto\\", local:\\"sys_id\\"). Expected
elements are <{}table>,<{}display_value>,<{}display_name>,
<{}error_message>,<{}sys_id>,<{}status_message>,<{}status>
(同样,为了易读性而包裹着线条。)
使用apache-cxf。
答案 0 :(得分:6)
在明确回答您的问题之前,似乎需要一些背景信息。
在XSD中,在复杂类型定义中声明的元素被称为 local 到该类型。 (另一种方法是独立地声明它们作为顶级元素;然后它们是全局或顶级。并非巧合的是,顶级元素是那些声明的元素位于架构文档的顶层,即那些是 xsd:schema 的子级。)
在XSD架构中声明的每个元素都有一个由命名空间名称和本地名称组成的名称。与XML名称一样,名称空间名称可以为null。当元素的名称具有非空命名空间名称时,它被称为 namespace-qualified; 当命名空间名称为null时,相反,元素的名称是 unqualified 。
顶级元素声明从封闭的 xsd:schema 元素的 targetNamespace 属性中获取其命名空间。另一方面,局部元素声明提出了一个设计问题:它们是否进入目标命名空间(即它们的名称是否应该是名称空间限定的)?或者他们应该有不合格的名字?
在XSD用户社区中有两种思想流派,负责的工作组中有两种思想流派。有些人认为在模式文档中为命名空间 foo 声明的任何元素应该在命名空间 foo 中 - 毕竟,命名空间的一个功能是告诉你元素来自,这是寻找文档的第一步。其他人认为本地元素依赖于它们的包含类型,就像属性一样 - 本地属性具有不合格的名称。双方都同意的一点是,其他人都很疯狂,没有一个有两个脑细胞可以相互摩擦的人真的可以相信事情应该那样。
本地元素声明的 form 属性用于控制所讨论的本地元素是否具有限定名称或非限定名称;不出所料,它可以采用的两个值是qualified
和unqualified
。 xsd:schema 元素上的 elementFormDefault 属性用于指定哪些值应该是当前架构文档中的默认值;它的值默认为unqualified
,但明确指定它几乎总是好的做法,否则一些读者会感到困惑。
根据该背景信息,现在可以回答您的问题:为什么没有elementFormDefault="qualified"
此回复无效,这是正确的做法?
在架构中声明的 insertResponse 元素是顶级的,具有扩展名称(http://www.xpto.com/xpto,insertResponse) - 有时扩展名称以{{{3]的形式编写insertResponse,显然有时(如错误信息所示),表格为insertResponse @ http://www.xpto.com/xpto。
当架构文档未指定elementFormDefault = "qualified"
时,本地元素名称的形式默认为unqualified
。这意味着'sys_id','table','display_name'和其他本地元素的扩展名称都具有null命名空间部分,因此它们的扩展名称为{} sys_id,{} table,{} display_name等。但是您显示的文档具有
<insertResponse xmlns="http://www.xpto.com/xpto">
<sys_id>something</sys_id>
<table>something</table>
<display_name>number</display_name>
...
insertResponse 上的默认命名空间声明确保第一个子元素中作为“sys_id”给出的名称扩展为{http://www.xpto.com/xpto} sys_id,对于其他子项也是如此。在几乎所有XML技术中匹配扩展名称的基本规则是像{{{}}}这样的显式命名空间名称与空命名空间名称{}不匹配。因此,元素名称{http://www.xpto.com/xpto} sys_id与名为{} sys_id的元素的元素声明不匹配。在实例中找不到模式所需的元素,并且在实例中找到一个元素,该元素在声明中不匹配任何内容。所以insertResponse元素无效。
当架构文档指定elementFormDefault="qualified"
时,本地元素sys_id等是命名空间限定的。因此,在实例文档中找到的扩展名称和与模式中的声明关联的扩展名称都是相同的,即{http://www.xpto.com/xpto} sys_id。一切都很好,文档是有效的,生活是好的,或者至少与使用SOAP时一样好。
底线:响应消息的创建者和架构的创建者目前尚未就响应应该是什么样子达成一致。 正确的方法是让他们都了解命名空间限定如何在XML和XSD中工作,并就响应应采取的形式达成一致。
祝你好运。