根据从 WSDL 中提取的多个模式验证 XML

2024-02-05

我尝试使用 SAAJ 手动处理 Web 服务请求,但仍然根据 Web 服务的 WSDL 架构验证接收到的请求。这个特定的 WSDL 包含多个元素,我使用 wsdl4j 提取这些元素,当我尝试创建新的验证器时,我收到一条错误消息,说明该验证器无法将一个模式内的引用解析为在另一个元素中定义的元素:

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

我已将实际的 WSDL 和代码精简为一些小内容,以创建可重现的内容。 “simple.wsdl”也在 Soap-UI 中正确加载。这是在 Windows 7 上使用 jdk1.7.0_51。

请注意,我注意到此问题的原始 WSDL 是由 TIBCO BusinessWorks 生成的,因此我不认为这是无效 WSDL 的问题。

我在 SO 上看到过与此类似的其他问题,但提供的解决方案似乎并不完全满足我的情况,所以我想我会再问一次。

有谁知道发生了什么事以及我如何才能使其正常工作?

测试代码:

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>

我必须使用 LSResourceResolver 并将命名空间声明从 wsdl 文档复制到模式元素才能完成这项工作。这是代码:

public static Schema makeSchema(String pathToWsdl)
    throws ParserConfigurationException, IOException, SAXException, InstantiationException, IllegalAccessException, ClassNotFoundException {
    // read wsdl document
    File wsdlFile = new File(pathToWsdl);
    DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
    dbFactory.setNamespaceAware(true);
    DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
    Document wsdlDoc = dBuilder.parse(wsdlFile);

    // read namespace declarations from wsdl document, in case they are referred from a schema
    NamedNodeMap attributes = wsdlDoc.getDocumentElement().getAttributes();
    Map<String, String> namespacesFromWsdlDocument = new HashMap<>();
    for (int i = 0; i < attributes.getLength(); i++) {
        Node n = attributes.item(i);
        if (n.getNamespaceURI() != null && n.getNamespaceURI().equals("http://www.w3.org/2000/xmlns/")) {
            namespacesFromWsdlDocument
                .put(n.getLocalName(), n.getNodeValue());
        }
    }

    // read the schema nodes from the wsdl
    NodeList schemas = wsdlDoc.getElementsByTagNameNS("http://www.w3.org/2001/XMLSchema", "schema");
    Map<String, DOMSource> sources = new HashMap<>();
    for (int i = 0; i < schemas.getLength(); i++) {
        // create a document for each schema and copy the source schema
        Document schema = dBuilder.newDocument();
        Element schemaElement = (Element)schema.importNode(schemas.item(i), true);

        // add all non-existing namespace declarations from the wsdl node
        String targetNs = schemaElement.getAttribute("targetNamespace");
        for (Map.Entry<String, String> ns : namespacesFromWsdlDocument.entrySet()) {
            String name = ns.getKey();
            String value = ns.getValue();
            if (schemaElement.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", name) == null) {
                schemaElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" + name, value);
            }
        }

        // map schemas by their target namespace
        schema.appendChild(schemaElement);
        DOMSource domSource = new DOMSource(schema);
        sources.put(targetNs, domSource);
    }

    SchemaFactory factory =
        SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);

    // Create a ResourceResolver that can find the correct schema from the map
    DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();

    final DOMImplementationLS domImplementationLS = (DOMImplementationLS) registry.getDOMImplementation("LS");
    factory.setResourceResolver(new LSResourceResolver() {
        @Override public LSInput resolveResource(String type, String namespaceURI, String publicId, String systemId, String baseURI) {
            Source xmlSource = sources.get(namespaceURI);
            if (xmlSource != null) {
                LSInput input = domImplementationLS.createLSInput();
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                Result outputTarget = new StreamResult(outputStream);
                try {
                    TransformerFactory.newInstance().newTransformer().transform(xmlSource, outputTarget);
                } catch (TransformerException e) {
                    e.printStackTrace();
                }
                InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
                input.setByteStream(is);
                input.setSystemId(systemId);
                return input;
            } else {
                return null;
            }
        }
    });

    // create the schema object from the sources
    return factory.newSchema(sources.values().toArray(new DOMSource[]{}));
}

这里也回答了同样的问题:Java,根据 WSDL 中的嵌入模式验证 XML https://stackoverflow.com/questions/37546182/java-validate-xml-against-an-embedded-schema-in-wsdl

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据从 WSDL 中提取的多个模式验证 XML 的相关文章

随机推荐

  • 在 ClosedXML 中应用多个过滤器 (SetAutoFilter)

    我通过 ClosedXML 对多个列应用过滤器 但是 仅应用最后一项 这些过滤器在单独使用时会起作用 我怎样才能应用所有这些 我在这里发现了类似的问题ClosedXML Excel 按多列中的值过滤行 https stackoverflow
  • Chrome 扩展页面 popup.html 无法调整大小

    所以我有这个 Chrome 扩展程序 可以从互联网上加载一些内容 基本上 用户单击弹出图标 然后后台页面中的一些 JavaScript 加载一些页面 从中解析图像并将其放入 popup html 页面中 问题是 popup html 没有调
  • 在 C# 中扩展枚举

    我想知道是否可以扩展 C 中的 Enum 类型来实现我的自定义 Enum GetValues type 并像 Enum GetMyCustomValues type 那样调用它 我正在尝试实现这样的事情 public static bool
  • 使用 C++ 命名参数习惯用法的更好方法?

    我一直在为 Windows 开发一个 GUI 库 作为个人业余项目 不希望有用 对于我的主窗口类 我设置了选项类的层次结构 使用命名参数惯用语 http www parashift com c faq lite named paramete
  • Microsoft Edge:本地/会话存储无法在新选项卡中工作

    我正在开发一个托管在 Azure 中的 Web 应用程序 我在 MS Edge 版本 20 10525 0 0 上尝试过 但遇到了以下问题 我有一个带有 target blank 的链接 可以在新选项卡中打开页面 在该链接的点击事件中 我将
  • 将日期字符串转换为正确的格式

    我收到服务器的响应 并且需要将日期字符串转换为日期 2017 年 6 月 29 日星期四 07 15 25 0000 我正在尝试将字符串转换为人类可读的格式 谁能建议如何将此字符串转换为日期 您需要将日期字符串解析为Date对象使用Date
  • 可捕获的致命错误:类 mysqli 的对象无法转换为字符串

    所以我有一个问题 我对 PHP 非常陌生 并且在更新数据库上的字符串时遇到问题 它抛出了这个错误 Catchable fatal error Object of class mysqli Could not be Converted to
  • 获取类型的默认构造函数的最有效方法

    获取 System Type 的默认构造函数 即不带参数的实例构造函数 的最有效方法是什么 我正在思考下面的代码 但似乎应该有一种更简单更有效的方法来做到这一点 Type type typeof FooBar BindingFlags fl
  • 如何从对象中深度删除空值、空对象和空数组

    我有一个看起来像这样的对象 var myObject a b c d 2 e 2 f g h i null 2 我想删除空值和空对象 数组和对象 使其看起来像 a c d 2 e 2 i 2 该函数应删除空值 空对象和空数组 有什么优雅的方
  • 找出远程服务器上git的版本

    我正在本地计算机上寻找 git 命令 我可以运行该命令来查找远程服务器上运行的 git 版本 如果这可能的话 现代 git 服务器 始于git 1 7 12 1 https github com git git commit ff5effd
  • 运行Hadoop时如何避免OutOfMemoryException?

    我正在运行一个超过 1 5 TB 数据的 Hadoop 作业 并进行大量模式匹配 我有几台每台 16GB RAM 的机器 我总是得到OutOfMemoryException使用这些数据来完成这项工作 我正在使用 Hive 我想知道如何最佳设
  • 多行函数调用的左括号必须是该行的最后一个内容

    我在 PHP 文件中写入以下代码 public function ScriptsStyles wp enqueue style fontawesome plugins url css font awesome css FILE array
  • WPF:“名称”和“x:名称”之间有什么区别? [复制]

    这个问题在这里已经有答案了 可能的重复 在 WPF 中 x Name 和 Name 属性之间有什么区别 https stackoverflow com questions 589874 in wpf what are the differe
  • Android CoroutineScope 完成后自动取消

    我想知道是否coroutineScope工作完成后将自动取消 假设我创建了一个coroutineScope在自定义类中而不是 ViewModel类或Fragment Activity class class MyClass private
  • firebase存储cors奇怪的行为

    我正在构建一个应用程序 让用户看到一组缩小的图像 然后按 确定 让应用程序下载所有原始文件 将它们放入 zip 文件中并发送 zip 文件 该应用程序使用polymer polymerfire firebase 包括存储 在上传图像的过程中
  • 组合两个 Linq lambda 表达式

    Expression
  • 没有 AppBar 的 Flutter 布局

    我需要一个没有应用栏的布局 所以最明显的方法是省略appbar标签上的Scaffold但如果我这样做 内容就会出现在状态栏下方 如下所示 正如您所看到的 我的蓝色容器从状态栏下方开始 但事实并非如此 因此我必须手动设置容器的边距 这不太好
  • 在文件夹中查找最新文件并打开它(vba 访问)

    我正在尝试使用以下代码通过访问按钮宏打开文件夹中的最新文件 使用 if 语句进行测试 没有发现任何问题 但是一旦我使用了 do while 我就收到了运行时 6 溢出的错误消息 does len dir 不能使用循环 下面是我的代码 Pri
  • 在终端中,将多个文件夹合并为一个

    我有一个由 WDBackup 西部数据外置硬盘备份实用程序 创建的备份目录 其中包含每天备份的目录以及备份内容的增量内容 所以层次结构看起来像这样 20100101 My Documents Letter1 doc My Music Bes
  • 根据从 WSDL 中提取的多个模式验证 XML

    我尝试使用 SAAJ 手动处理 Web 服务请求 但仍然根据 Web 服务的 WSDL 架构验证接收到的请求 这个特定的 WSDL 包含多个元素 我使用 wsdl4j 提取这些元素 当我尝试创建新的验证器时 我收到一条错误消息 说明该验证器