根据嵌套在wsdl:types

时间:2017-06-08 01:54:14

标签: ruby xml xsd nokogiri xsd-validation

我需要根据XSD验证XML文件,这些XSD嵌套在从Web服务检索到的WSDL文件中的<wsdl:types></wsdl:types>内。

<wsdl:types></wsdl:types>内,有几个<xs:schema>。我正在使用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>,我不认为它本身就是一个问题因为nokogiri在我实例化{schema时没有抛出错误{1}}对象。

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>

1 个答案:

答案 0 :(得分:1)

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

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

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