I found no direct way on how to validate an element against a XSD type, using XmlBeans. But I found a workaround by dynamically creating a schema for the missing element declaration:
/**
* Validates an XML element (it needs not be the document root) against a type declared in an XSD-schema.
*
* @param xmlObject XML element being validated
* @param schemas compiled XML schema(s) used for the validation
* @param xmlObjectType Qualified name of the schema type in <code>schemas</code> against which the element validation is performed
* @throws XmlException thrown in case of a parsing or validation error
*/
public static void validate(XmlObject xmlObject, SchemaTypeSystem schemas, QName xmlObjectType) throws XmlException {
Node node = xmlObject.getDomNode();
//..... some argument checking here .....
String elemName = node.getLocalName();
String elemNamespace = node.getNamespaceURI();
String typeName = xmlObjectType.getLocalPart();
String typeNamespace = xmlObjectType.getNamespaceURI();
String schemasKey = elemName+"@"+elemNamespace +"," +typeName+"@"+typeNamespace; //perhaps it's sufficient
// Prepare schema
SchemaTypeSystem loader = schemas;
SchemaGlobalElement schemaElem = loader.findElement(new QName(elemNamespace, elemName));
if (schemaElem != null) {
QName elemQName = schemaElem.getType().getName();
if (!elemQName.getLocalPart().equals(typeName) || !elemQName.getNamespaceURI().equals(typeNamespace))
throw new IllegalArgumentException("Requested type " +typeName+"@"+typeNamespace
+" of xmlObject is different from its actual type " +elemQName.getLocalPart()+"@"+elemQName.getNamespaceURI() +" in provided schema(s)");
}
else {
//the schema does not contain the xmlObject element declaration => add it (artificially)
String helperSchema = ""
+ "<xs:schema attributeFormDefault=\"unqualified\" elementFormDefault=\"qualified\"\n"
+ " targetNamespace=\"" +elemNamespace +"\"\n"
+ " xmlns=\"" +elemNamespace +"\"\n"
+ " xmlns:t=\"" +typeNamespace +"\"\n"
+ " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+ "\n"
+ " <xs:element name=\"" +elemName +"\" type=\"t:" +typeName +"\"/>\n"
+ "\n"
+ "</xs:schema>\n";
loader = XmlBeans.compileXsd(schemas, // extend the schema
new XmlObject[]{
XmlObject.Factory.parse(helperSchema, new XmlOptions().setLoadLineNumbers().setLoadMessageDigest()
.setDocumentSourceName(schemasKey))
}, null,
new XmlOptions().setErrorListener(null).setCompileDownloadUrls().setCompileNoPvrRule());
}
// validate the element using the loader in a standard way
// (see the link above, for instance)
validate(xmlObject, loader);
}
I receive an XmlObject on the input, but one would usually use a File object instead. In the implementation, resorting to DOM may not be optimal, though - if I new XmlBeans better, the code could be improved.