Java, Validate XML against an embedded schema in WSDL

不想你离开。 提交于 2019-12-20 01:38:34

问题


I have a .wsdl file with an embedded schema. I want to validate an XML file/string using that .wsdl file (the same way you would validate against an .xsd). The schema is between the <types> tag. I have this so far:

public boolean validate(String xmlString) {
    try {
        // Convert to input stream
        InputStream xml = new ByteArrayInputStream(xmlString.getBytes());

        SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = schemaFactory.newSchema(new File("wsdl_filepath"));

        // Validate against wsdl
        Validator validator = schema.newValidator();
        validator.validate(new StreamSource (xml));

        // XML Message is valid
        return true;

    } catch (SAXException e) {
        e.printStackTrace();
        return false;

    } catch (IOException e) {
        e.printStackTrace();
        return false;
    }
}

This doesn't work, however. This validator works if validating against an .xsd. I'm not sure how to modify it to validate against the embedded schema.

Any help would be appreciated, thank you!


回答1:


Here is what worked for me to extract the schemas from wsld:

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[]{}));
}


来源:https://stackoverflow.com/questions/37546182/java-validate-xml-against-an-embedded-schema-in-wsdl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!