SOAP 响应架构验证

发布于 2024-09-29 04:57:28 字数 4159 浏览 4 评论 0原文

简短版本:

我正在尝试编写一个 XSD 来验证我的 SOAP 服务的响应。我觉得有必要导入 http:// schemas.xmlsoap.org/soap/envelope/ 而不是重新定义 SOAP 元素,如 Envelope、Head 和 Body,但是 xmlsoap.org 的 Body 模式定义对于我的使用来说太宽泛了 - - 一旦我导入 SOAP 架构,我的 XSD(我为我的服务精心定制的)就会突然验证所有 SOAP 消息。

我应该如何处理 XSD 中 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 验证来自我的服务的响应。 因此,当我尝试使用 PHP 的 DOMDocument::schemaValidateSource() 功能通过架构(第二个片段)验证示例响应(第一个 XML 片段)时,我手动编写了一个 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>

所有类型,验证者指出了我的第一个明显错误:

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

“哎呀,废话,”我想,“这些元素是在 SOAP 的命名空间中定义的,所以我需要导入 SOAP 的 XSD。”

所以我编辑了我的 XSD 并添加了一个导入:

<xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/>

它起作用了!当我使用 XSD 验证肥皂响应时,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>

我尝试使用这个完全不相关的架构来验证我的肥皂响应...

乍一看,该架构,根本没有描述此消息,还验证了肥皂响应。

然后我意识到 XSD 的架构一定是响应针对这两个不同架构进行验证的原因。我从 http://schemas.xmlsoap.org/soap/envelope/ 将 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 的定义?

Short version:

I'm trying to write an XSD that will validate my SOAP service's responses. I feel compelled to just import http:// schemas.xmlsoap.org/soap/envelope/ instead of redefining the SOAP elements like Envelope, Head, and Body, but that xmlsoap.org schema definition of Body is too broad for my use--as soon as I import the SOAP Schema, suddenly my XSD (that I've carefully tailored to my service) validates all SOAP messages.

How should I handle the definition of the SOAP envelope, head, body in my XSD?

I suspect the problem is that I'm trying to re-use other schemas that I shouldn't be trying to re-use. Certainly, those Schemas for SOAP are intended to define what (all) SOAP messages should look like. And maybe I just need to define in my schema what I want my particular soap body to look like.

I might have just answered my own question. Maybe someone has a different solution?

Long version:

I'm having a little trouble authoring an XSD to describe the response message from one of my SOAP services.

Here's an example response from my service that I'm trying to validate:

<?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>

My goal is to validate responses from my service with an XSD.
So, I hand-authored an XSD that describes all the types that belong in my service's 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>

When I tried to validate the example response (first XML snippet) with the Schema (2nd snippet) using PHP's DOMDocument::schemaValidateSource() functionality, the validator pointed out my first obvious mistake:

Element 'soap:Envelope': No matching global declaration available

"Oops, duh," I thought, "Those elements are defined in SOAP's namespace, so I need to import SOAP's XSD."

So I edited my XSD and added an import:

<xsd:import namespace="http://schemas.xmlsoap.org/soap/envelope/" schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/>

And it worked! DOMDocument::schemaValidateSource returns true when I validate the soap response with the XSD.

Then, as a sanity check, I took a different soap response XSD I had lying around:

<?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>

And I tried to validate my soap response with this completely unrelated Schema...

And the schema that, at first glance, doesn't describe this message at all, also validates the soap response.

Then I realize that XSD's Schema must be the reason the response is validating against these two different schemas. The SOAP schema I'm importing from http://schemas.xmlsoap.org/soap/envelope/ defines the Body element to be:

<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>

Which allows the contents of the Body tag to be basically anything.

That makes sense, the purpose of XSD's XSD is to define what ALL XSDs should look like, not just mine.

So my question is, how should I build an XSD to validate these SOAP responses, reusing existing SOAP XSDs if possible?

Here's the direction I've been pursuing...

  • I guess I could throw xmlsoap.org's XSD schema out the window and redefine Envelope and Body myself, specifying exactly what should show up in the Body element. But I feel like I'll end up basically having a copy of all the soap elements inside my own XSD, with a slightly different Head and Body definition, and that feels like a violation of DRY.
  • Is there a way I can import xmlsoap.org's XSD but then override the definition of soap:Body from inside my XSD?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

眼睛会笑 2024-10-06 04:57:28

您应该使用 SOAP Web 服务框架来做到这一点。 维基百科页面上列出了许多针对各种编程语言的信息。您编写 WSDL 来指定您的 Web 服务 API,并在其中导入 XSD 来定义有效负载格式(契约优先方法)。使用框架提供的wsdl2xxx工具生成API存根。您编写 API 实现代码。该框架将负责剩下的工作(处理 SOAP 消息并绑定到您的实现代码)。

You should use a SOAP web service framework to do that. There are many for various programming languages listed on the wikipedia page. You write a WSDL to specify your web service API, and in which you import your XSD to define the payload formats (contract-first approach). Use the wsdl2xxx tool provided by the framework to generate the API stub. You write the API implementation code. The framework will take care of the rest (processing the SOAP messages and binding to your implementation code).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文