问题
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