2014-01-20 59 views
1

提取多個架構驗證XML我想要手動處理用SAAJ Web服務請求,但仍驗證對WSDL web服務的架構接收到的請求。這個特定的WSDL包含多個元素,我使用wsdl4j進行提取,當我嘗試創建一個新的Validator時,我收到一條有關Validator無法解析一個模式中的引用的錯誤消息,以在另一個定義的元素:對從WSDL

org.xml.sax.SAXParseException; src-resolve: Cannot resolve the name 'ns0:CustomerNumber' to a(n) 'element declaration' component. 

我wittled實際WSDL和代碼到一些小創造一些可再現。 「simple.wsdl」也在Soap-UI中正確加載。這是在Windows 7上使用jdk1.7.0_51。

注意,是由TIBCO BusinessWorks產生與我注意到了這個問題,原來的WSDL,所以我不相信這是無效的WSDL的問題。

我看到的,這樣與此類似的其他問題,但所提供的解決方案似乎並不完全符合我的情況,所以我想我會再問。

有沒有人知道發生了什麼,以及如何讓這個工作?

測試代碼:

import java.util.ArrayList; 

import javax.wsdl.Definition; 
import javax.wsdl.extensions.schema.Schema; 
import javax.wsdl.factory.WSDLFactory; 
import javax.wsdl.xml.WSDLReader; 
import javax.xml.XMLConstants; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.validation.SchemaFactory; 
import javax.xml.validation.Validator; 

import org.junit.Test; 
import org.w3c.dom.Element; 

public class TestIt { 
    @Test 
    public void testWSDLSchema() throws Exception { 
     WSDLFactory wsdlFactory = WSDLFactory.newInstance(); 
     WSDLReader reader   = wsdlFactory.newWSDLReader(); 
     Definition wsdlDefinition = reader.readWSDL("test/resources/simple.wsdl"); 

     ArrayList<Element> wsdlSchemas = new ArrayList<Element>(); 

     for (Object o : wsdlDefinition.getTypes().getExtensibilityElements()) { 
      if (o instanceof Schema) { 
       wsdlSchemas.add(((Schema) o).getElement()); 
      } 
     } 

     SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
     ArrayList<DOMSource> asrcs = new ArrayList<DOMSource>(); 

     for (Element e : wsdlSchemas) { 
      asrcs.add(new DOMSource(e)); 
     } 
     DOMSource sources[] = asrcs.toArray(new DOMSource[0]); 
     javax.xml.validation.Schema schema = factory.newSchema(sources); 

     Validator schemaValidator = schema.newValidator(); 
    } 
} 

完整堆棧跟蹤:

Retrieving document at 'test/resources/simple.wsdl'. 

org.xml.sax.SAXParseException; src-resolve: Cannot resolve the name 'ns0:CustomerNumber' to a(n) 'element declaration' component. 
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:198) 
    at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:134) 
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:437) 
    at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:347) 
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaErr(XSDHandler.java:4166) 
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.reportSchemaError(XSDHandler.java:4145) 
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.getGlobalDecl(XSDHandler.java:1678) 
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDElementTraverser.traverseLocal(XSDElementTraverser.java:170) 
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.traverseLocalElements(XSDHandler.java:3618) 
    at com.sun.org.apache.xerces.internal.impl.xs.traversers.XSDHandler.parseSchema(XSDHandler.java:633) 
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadSchema(XMLSchemaLoader.java:616) 
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:574) 
    at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader.loadGrammar(XMLSchemaLoader.java:540) 
    at com.sun.org.apache.xerces.internal.jaxp.validation.XMLSchemaFactory.newSchema(XMLSchemaFactory.java:252) 
    at TestIt.testWSDLSchema(TestIt.java:37) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:160) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:202) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:65) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 

WSDL:

<?xml version="1.0" encoding="UTF-8"?> 
<wsdl:definitions xmlns:ns10="http://www.abc.com/ServiceA" 
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
        xmlns:ns13="http://www.abc.com/Common" 
        xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" 
        xmlns:ns2="http://www.abc.com/DetailsResponse" 
        xmlns:ns3="http://www.abc.com/ErrorSchema" 
        xmlns:ns1="http://www.abc.com/DetailsRequest" 
        xmlns:tns="http://www.abc.com/Service" 
        name="Untitled" 
        targetNamespace="http://www.abc.com/Service"> 
    <wsdl:types> 
     <xs:schema 
       xmlns="http://www.abc.com/DetailsRequest" 
       xmlns:ns0="http://www.abc.com/Common" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       targetNamespace="http://www.abc.com/DetailsRequest" 
       elementFormDefault="qualified" 
       attributeFormDefault="unqualified"> 
      <xs:import namespace="http://www.w3.org/XML/1998/namespace"/> 
      <xs:import namespace="http://www.abc.com/Common"/> 
      <xs:element name="DetailsRequest"> 
       <xs:complexType> 
        <xs:sequence> 
         <xs:element ref="ns1:RequestBody"/> 
        </xs:sequence> 
       </xs:complexType> 
      </xs:element> 
      <xs:element name="RequestBody"> 
       <xs:complexType> 
        <xs:sequence> 
         <xs:element ref="ns0:CustomerNumber"/> 
        </xs:sequence> 
       </xs:complexType> 
      </xs:element> 
     </xs:schema> 
     <xs:schema 
       xmlns="http://www.abc.com/DetailsResponse" 
       xmlns:ns0="http://www.abc.com/Common" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       targetNamespace="http://www.abc.com/DetailsResponse" 
       elementFormDefault="qualified" 
       attributeFormDefault="unqualified"> 
      <xs:import namespace="http://www.abc.com/Common"/> 
      <xs:element name="DetailsResponse"> 
       <xs:complexType> 
        <xs:sequence> 
         <xs:element ref="ns0:AccountNumber"/> 
        </xs:sequence> 
       </xs:complexType> 
      </xs:element> 
     </xs:schema> 
     <xs:schema 
       xmlns="http://www.abc.com/Common" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       targetNamespace="http://www.abc.com/Common" 
       elementFormDefault="qualified" 
       attributeFormDefault="unqualified"> 
      <xs:element name="CustomerNumber"> 
       <xs:simpleType> 
        <xs:restriction base="xs:string"> 
         <xs:maxLength value="20"/> 
        </xs:restriction> 
       </xs:simpleType> 
      </xs:element> 
      <xs:element name="AccountNumber"> 
       <xs:simpleType> 
        <xs:restriction base="xs:string"> 
         <xs:maxLength value="20"/> 
        </xs:restriction> 
       </xs:simpleType> 
      </xs:element> 
     </xs:schema> 
     <xs:schema 
       xmlns="http://www.abc.com/ErrorSchema" 
       xmlns:xs="http://www.w3.org/2001/XMLSchema" 
       targetNamespace="http://www.abc.com/ErrorSchema" 
       elementFormDefault="qualified" 
       attributeFormDefault="unqualified"> 
      <xs:element name="ErrorSchema"> 
       <xs:complexType> 
        <xs:sequence> 
         <xs:element name="ErrorResponseBody" type="xs:string"/> 
        </xs:sequence> 
       </xs:complexType> 
      </xs:element> 
     </xs:schema> 
    </wsdl:types> 
    <wsdl:service name="ServiceA"> 
     <wsdl:port name="ServiceAEndpoint" binding="tns:ServiceABinding"> 
      <soap:address location="http://localhost:7232/ServiceA/ServiceAEndpoint"/> 
     </wsdl:port> 
    </wsdl:service> 
    <wsdl:portType name="ServiceA"> 
     <wsdl:operation name="GetDetails"> 
      <wsdl:input message="tns:DetailsRequest"/> 
      <wsdl:output message="tns:DetailsResponse"/> 
      <wsdl:fault name="fault1" message="tns:DetailsErrorResponse"/> 
     </wsdl:operation> 
    </wsdl:portType> 
    <wsdl:binding name="ServiceABinding" type="tns:ServiceA"> 
     <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> 
     <wsdl:operation name="GetDetails"> 
      <soap:operation style="document" soapAction="/ServiceA/ServiceAEndpoint/GetDetails"/> 
      <wsdl:input> 
       <soap:body use="literal" parts="DetailsRequest"/> 
      </wsdl:input> 
      <wsdl:output> 
       <soap:body use="literal" parts="DetailsResponse"/> 
      </wsdl:output> 
      <wsdl:fault name="fault1"> 
       <soap:fault use="literal" name="fault1"/> 
      </wsdl:fault> 
     </wsdl:operation> 
    </wsdl:binding> 
    <wsdl:message name="DetailsRequest"> 
     <wsdl:part name="DetailsRequest" element="ns1:DetailsRequest"/> 
    </wsdl:message> 
    <wsdl:message name="DetailsResponse"> 
     <wsdl:part name="DetailsResponse" element="ns2:DetailsResponse"/> 
    </wsdl:message> 
    <wsdl:message name="DetailsErrorResponse"> 
     <wsdl:part name="DetailsErrorResponse" element="ns3:ErrorSchema"/> 
    </wsdl:message> 
</wsdl:definitions> 
+0

您是否嘗試按照導入的相反順序提供模式? – jtahlborn

+0

我做過了,在這種簡單的情況下,它可以工作。我只是使用wsdlSchemas.add(0,...)在代碼中顛倒順序而不修改實際的WSDL。但是,對於真正的WSDL,這沒有幫助。我想在這種情況下,依賴關係有點竅門? –

+0

請參閱下面的答案。 – jtahlborn

回答

0

我覺得SchemaFactory對它如何導致進口感到「啞巴」。我相信,如果您以相反的順序(從最低級到最高級)提供模式,那就應該有效。在您有更復雜的依賴關係(或同一名稱空間的多個模式)的情況下,您可能需要實現自定義LSResourceResolver並將其設置爲SchemaFactory

+0

你確定嗎? SchemaFactory.newSchema(Source [])的javadocs說:「生成的模式包含來自指定源的組件。如果所有這些源都已導入,並使用適當的schemaLocation和namespace值,可以實現相同的結果到單個模式文檔使用不同的targetNamespace並且沒有它自己的組件,如果導入元素以與源相同的順序給出「。我可能會讀這個錯誤,但對我來說,這聽起來像一個LSResourceResolver不應該是必要的。 –

+0

@MaartenBoekhold - 我不知道你的綜合模式如何幫助任何東西。您必須在導入之前提供導入的模式,因此合成模式最終會成爲最後一個? – jtahlborn