针对嵌套WSDL中的模式验证XML文档:类型



我有XML文件,我需要针对从Web服务检索的WSDL文件中嵌套<wsdl:types></wsdl:types>中嵌套的XSD进行验证。

<wsdl:types></wsdl:types>内部有几个<xs:schema> s。我正在使用Ruby Gem nokogiri加载XML文件并针对所述XSD进行验证,但是,运行程序时我会遇到以下错误:

Element '{http://schemas.xmlsoap.org/soap/envelope/}Envelope': No 
matching global declaration available for the validation root.

到目前为止,我已经提取了<xs:schema> S(所有4个(,然后将它们复制到schema.xsd文件中。

代码

require 'rubygems'
require 'nokogiri'
def validate(document_path, schema_path)
  schema = Nokogiri::XML::Schema(File.read(schema_path))
  document = Nokogiri::XML(File.read(document_path))
  schema.validate(document)
end

validate('data.xml', 'schema.xsd').each do |error|
  puts error.message
end

因此,基本上我的schema.xsd中有多个<xs:schema> s,我认为这本身并不是一个问题,因为当我实例化schema对象时,nokogiri不会丢弃错误。

schema.xsd

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/">
  <xs:element name="anyType" nillable="true" type="xs:anyType"/>
  <xs:element name="anyURI" nillable="true" type="xs:anyURI"/>
  <!-- data in here -->
</xs:schema>
<!-- three more xs:schema tags removed for brevity -->

data.xml

<?xml version='1.0' ?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
  <env:Header />
  <env:Body>
    <CreatePerson xmlns="https://person.example.com/">
      <oMessageType xmlns:epa="http://schemas.datacontract.org/2004/07/whatever" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:array="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
        <person:bodyField>
            <!-- data in here -->
        </person:bodyField>
        <!-- more data in here -->
      </oMessageType>
    </CreatePerson>
  </env:Body>
</env:Envelope>

是的,WSDL不是XSD scheam,因此您需要通过编程手动或自动提取模式部分。

这是示例代码,您需要重构并在代码中使用。

str = <<EOF
    <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://www.examples.com/wsdl/HelloService.wsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="HelloService" targetNamespace="http://www.examples.com/wsdl/HelloService.wsdl">
    <types>
        <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/">
          <element name="anyType" nillable="true" type="anyType"/>
          <element name="anyURI" nillable="true" type="anyURI"/>
          <!-- data in here -->
        </schema>
    </types>
    <message name="SayHelloRequest">
        <part name="firstName" type="xsd:string"/>
    </message>
    <message name="SayHelloResponse">
        <part name="greeting" type="xsd:string"/>
    </message>
    <portType name="Hello_PortType">
        <operation name="sayHello">
            <input message="tns:SayHelloRequest"/>
            <output message="tns:SayHelloResponse"/>
        </operation>
    </portType>
    <binding name="Hello_Binding" type="tns:Hello_PortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="sayHello">
            <soap:operation soapAction="sayHello"/>
            <input>
                <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice"/>
            </input>
            <output>
                <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="urn:examples:helloservice"/>
            </output>
        </operation>
    </binding>
    <service name="Hello_Service">
        <documentation>WSDL File for HelloService</documentation>
        <port name="Hello_Port" binding="tns:Hello_Binding">
            <soap:address location="http://www.examples.com/SayHello/"/>
        </port>
    </service>
</definitions>
EOF
require 'rubygems'
require 'nokogiri'
doc = Nokogiri::XML(str)
doc.root.children.each do |child|
    if child.node_name == 'types'
        types = child 
        # p types.inner_html
        xsd_doc = Nokogiri::XML(types.inner_html)
        # p xsd_doc.root
        xsd = Nokogiri::XML::Schema.from_document xsd_doc.root
    end
end

最新更新