XSD 在 Spring WS 中使用 AxiomSoapMessageFactory 时,验证失败并显示 UndeclaredPrefix

XSD validation fails with UndeclaredPrefix when using AxiomSoapMessageFactory in Spring WS

我正在使用 spring-ws 2.2.3 构建合同优先的 SOAP Web 服务。我的 XML 架构使用扩展,导致 XML 请求中的 xsi:type= 属性。由于某些响应可能非常大 (30MB),因此我使用 AxiomSoapMessageFactory 而不是默认的 SaajSoapMessageFactory,如 Spring WS docs 中所建议的那样。我使用 PayloadValidatingInterceptor 验证传入请求:

PayloadValidatingInterceptor interceptor = new PayloadValidatingInterceptor();
interceptor.setSchema(new ClassPathResource("format-service.xsd"));
interceptor.setValidateRequest(true);
interceptor.setValidateResponse(false); 

我的问题是我收到虚假的验证错误,这取决于在 XML 中声明命名空间的位置:如果它在有效负载中声明,那么一切正常:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" >
   <soapenv:Header/>
   <soapenv:Body>
      <sch:formatRequest xmlns:sch="http://example.com/springws/extension/schema">
         <sch:value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="sch:currencyType">
           <sch:amount>1000</sch:amount>
           <sch:currency>EUR</sch:currency>
         </sch:value>
      </sch:formatRequest>
   </soapenv:Body>
</soapenv:Envelope>

但是一旦我将 sch 名称空间声明移动到信封中:

<soapenv:Envelope xmlns:sch="http://example.com/springws/extension/schema" ...>

验证失败,我收到 SOAP 错误:

<faultcode>soapenv:Client</faultcode>
<faultstring xml:lang="en">Validation error</faultstring>
<detail>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">UndeclaredPrefix: Cannot resolve 'sch:currencyType' as a QName: the prefix 'sch' is not declared.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-elt.4.1: The value 'sch:currencyType' of attribute 'http://www.w3.org/2001/XMLSchema-instance,type' of element 'sch:value' is not a valid QName.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-type.2: The type definition cannot be abstract for element sch:value.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">UndeclaredPrefix: Cannot resolve 'sch:currencyType' as a QName: the prefix 'sch' is not declared.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-attribute.3: The value 'sch:currencyType' of attribute 'xsi:type' on element 'sch:value' is not valid with respect to its type, 'QName'.</spring-ws:ValidationError>
    <spring-ws:ValidationError xmlns:spring-ws="http://springframework.org/spring-ws">cvc-complex-type.2.1: Element 'sch:value' must have no character or element information item [children], because the type's content type is empty.</spring-ws:ValidationError>
</detail>

这对我来说似乎是 AxiomSoapMessageFactory / Axiom 实现中的错误(命名空间上下文丢失),因为在使用 SaajSoapMessageFactory 时两个请求都可以正常验证。请注意,验证仅在 xsi:type= 属性上失败。元素可以正确识别相同的命名空间。

我无法使用 SaajSoapMessageFactory,因为大型响应会占用大量内存。我在Spring forum and on SO中发现了类似的问题,但没有解决方案。感谢您的帮助!

原因是Spring-WS在OMXMLStreamReaderConfiguration对象中使用了OMContainer#getXMLStreamReader(). Instead it should use OMContainer#getXMLStreamReader(boolean, OMXMLStreamReaderConfiguration) and set the preserveNamespaceContext属性到true

您应该为 Spring-WS 提交错误,或者更好的是,修复问题并提交拉取请求。