SOAP响应模式验证

时间:2010-10-25 21:59:52

标签: soap xsd schema validation

简短版本:

我正在尝试编写一个XSD来验证我的SOAP服务的响应。我不得不导入http:// schemas.xmlsoap.org/soap/envelope/,而不是重新定义像Envelope,Head和Body这样的SOAP元素,但是Body的xmlsoap.org模式定义太宽泛了 - - 一旦我导入SOAP Schema,突然我的XSD(我已经为我的服务精心定制)验证了所有 SOAP消息。

我应如何处理XSD中SOAP信封,头部,身体的定义?

我怀疑问题是我正在尝试重新使用我不应该尝试重用的其他模式。当然,那些用于SOAP的Schema旨在定义(所有)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,它描述了我服务的肥皂中所有类型: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()功能验证带有Schema(第2个代码片段)的示例响应(第一个XML片段)时,验证器指出了我的第一个明显的错误:

  

元素'肥皂:信封':没有匹配的全球声明

“糟糕,呃,”我想,“这些元素是在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。

然后,作为一个完整性检查,我采取了不同的肥皂反应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>

我尝试用这个完全不相关的Schema来验证我的肥皂反应......

乍一看,根本没有描述此消息的模式,也验证了肥皂响应。

然后我意识到XSD的Schema必须是响应验证这两种不同模式的原因。我从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应该是什么样子,而不仅仅是我的。

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

这是我一直追求的方向......

  • 我想我可以将xmlsoap.org的XSD架构抛出窗口并自己重新定义Envelope和Body,准确指出Body元素中应该显示的内容。但我觉得我最终基本上会在我自己的XSD中拥有所有肥皂元素的副本,头部和身体的定义略有不同,这感觉就像是对DRY的侵犯。
  • 有没有办法可以导入xmlsoap.org的XSD,但是从我的XSD内部覆盖soap:Body的定义?

1 个答案:

答案 0 :(得分:0)

您应该使用SOAP Web服务框架来做到这一点。 wikipedia page上列出了多种编程语言。您编写一个WSDL来指定您的Web服务API,并在其中导入XSD来定义有效负载格式(合同优先方法)。使用框架提供的wsdl2xxx工具生成API存根。您编写API实现代码。该框架将处理其余的工作(处理SOAP消息并绑定到您的实现代码)。