SOAP响应架构验证

17

简短版:

我正在尝试编写一个XSD来验证我的SOAP服务的响应。我觉得只需导入http://schemas.xmlsoap.org/soap/envelope/而不是重新定义SOAP元素(如Envelope、Head和Body),但是xmlsoap.org对Body的模式定义对于我的用途来说太宽泛了——一旦我导入SOAP Schema,我的XSD(我已经仔细为我的服务量身定制)就会验证所有 SOAP消息。

我该如何处理XSD中SOAP信封、头和正文的定义?

我怀疑问题在于我试图重复使用其他不应该重复使用的模式。当然,那些用于SOAP的模式旨在定义(所有)SOAP消息应该看起来像什么。也许我只需要在我的模式中定义我想要的特定SOAP正文的外观。

我可能已经回答了自己的问题。也许有人有不同的解决方案?

长版:

我正在编写一个XSD来描述我的SOAP服务之一的响应消息,但遇到了一些困难。

以下是我正在尝试验证的服务的示例响应:

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
   <soap:Body>
      <helloResponse xmlns="http://justinfaulkner/wsdl/1.0">
         <Message>Hello, Justin!</Message>
         <Message>Your lucky numbers are: 329, 9</Message>
      </helloResponse>
   </soap:Body>
</soap:Envelope>

我的目标是使用XSD验证来自我的服务的响应。因此,我手动编写了一个XSD,描述了所有属于我的服务的soap:Body中的类型。

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://justinfaulkner/wsdl/1.0" xmlns:tns="http://justinfaulkner/wsdl/1.0">
   <xsd:complexType name="helloResponseType">
      <xsd:sequence>
         <xsd:element name="Message" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
      </xsd:sequence>
   </xsd:complexType>
   <xsd:element name="helloResponse" type="tns:helloResponseType"/>
</xsd:schema>

当我尝试使用PHP的DOMDocument :: schemaValidateSource()功能,使用模式(第二个片段)验证示例响应(第一个XML片段)时,验证器指出了我的第一个明显错误:

元素 'soap:Envelope':没有可用的匹配全局声明

“糟糕,嗯”,我想,“这些元素在SOAP的命名空间中定义,所以我需要导入SOAP的XSD。”
因此,我编辑了我的XSD并添加了一个导入。
<xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/>

它成功了!当我使用XSD验证SOAP响应时,DOMDocument :: schemaValidateSource返回true。

接下来,作为一个健全性检查,我拿出了一个不同的SOAP响应XSD:

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://justinfaulkner/wsdl/1.0" xmlns:tns="http://justinfaulkner/wsdl/1.0">
   <xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/>
   <xsd:complexType name="OtherServiceResponseType">
      <xsd:all>
         <xsd:element name="CompletionCode" type="xsd:string"/>
         <xsd:element name="ResponseMessage" type="xsd:string"/>
      </xsd:all>
   </xsd:complexType>
   <xsd:element name="OtherServiceResponse" type="tns:OtherServiceResponseType"/>
</xsd:schema>

我试图使用一个完全不相关的模式来验证我的SOAP响应...

然后,一开始看起来并没有描述这个消息的模式也验证了SOAP响应。

然后我意识到XSD的模式必须是响应针对这两个不同模式进行验证的原因。 我从http://schemas.xmlsoap.org/soap/envelope/导入的SOAP模式定义了Body元素为:

<xs:element name="Body" type="tns:Body" />
<xs:complexType name="Body" >
<xs:sequence>
  <xs:any namespace="##any" minOccurs="0" maxOccurs="unbounded" processContents="lax" />
</xs:sequence>
<xs:anyAttribute namespace="##any" processContents="lax" >
  <xs:annotation>
 <xs:documentation>
   Prose in the spec does not specify that attributes are allowed on the Body element
 </xs:documentation>
  </xs:annotation>
</xs:anyAttribute>
</xs:complexType>

这允许Body标记的内容基本上可以是任何东西。

这有道理,XSD的目的是定义所有XSD应该长成什么样子,而不仅仅是我的。

那么我的问题是,我应该如何构建一个XSD来验证这些SOAP响应,如果可能的话,重用现有的SOAP XSD?

以下是我一直在探索的方向...

  • 我想我可以放弃xmlsoap.org的XSD模式,并自己重新定义Envelope和Body,指定Body元素中应该显示的内容。但我觉得我最终将会在自己的XSD中拥有所有soap元素的副本,具有稍微不同的Head和Body定义,这感觉像是DRY的侵犯。
  • 是否有一种方法可以导入xmlsoap.org的XSD,然后从我的XSD内部覆盖soap:Body的定义?

你找到这个问题的解决方案了吗?我也遇到了完全相同的问题。 - Marc Quebrar Tan
感谢您详细的帖子。您的解决方案已经对我的具体问题有所帮助。 - sschmeck
1个回答

1

你应该使用一个SOAP Web服务框架来实现这个功能。维基百科页面wikipedia page列出了许多不同编程语言的框架。你需要编写一个WSDL文件来定义你的Web服务API,并在其中引入你的XSD文件以定义有效载荷格式(契约优先方法)。使用框架提供的wsdl2xxx工具生成API存根。你需要编写API实现代码,框架将负责其余部分(处理SOAP消息并绑定到你的实现代码)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接