Ruby 根据嵌套在wsdl:type中的模式验证XML文档

Ruby 根据嵌套在wsdl:type中的模式验证XML文档,ruby,xml,xsd,nokogiri,xsd-validation,Ruby,Xml,Xsd,Nokogiri,Xsd Validation,我有一些XML文件需要根据XSD进行验证,XSD嵌套在从web服务检索的WSDL文件中的中 在内部有几个s。我正在使用ruby gemnokogiri加载XML文件并根据所述XSD验证它们,但是,当我运行程序时,我遇到以下错误: Element '{http://schemas.xmlsoap.org/soap/envelope/}Envelope': No matching global declaration available for the validation root. 到目前为

我有一些XML文件需要根据XSD进行验证,XSD嵌套在从web服务检索的WSDL文件中的

内部有几个
s。我正在使用ruby gem
nokogiri
加载XML文件并根据所述XSD验证它们,但是,当我运行程序时,我遇到以下错误:

Element '{http://schemas.xmlsoap.org/soap/envelope/}Envelope': No 
matching global declaration available for the validation root.
到目前为止,我已经提取了
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
有多个
在那里,我不认为这本身就是一个问题,因为当我实例化
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

str=我继续重构了我的代码,就像您在这里所做的那样,但我仍然得到了相同的错误消息:@hyde主要的想法是搜索嵌入的模式元素并创建一个新文档,然后您可以根据新文档创建xsd。就这样。我的示例代码是一个工作副本,但对于ProjectPropose,此代码并不漂亮,对于测试,您可以复制wsdl字符串来替换
str
。对。这就是您的代码所做的——从WSDL中提取模式。但是,当我尝试使用提取的架构验证数据时,仍然会遇到相同的错误:元素“{}信封”:没有可用于验证根的匹配全局声明。假设您应该验证SOAP正文部分中的内容,因为您的架构是定义此xml,而不是定义整个信封。