We’re working on an XML import routine and needed to first validate the incoming documents against an XML Schema. Since I wasn’t able to find a working example on the web I pieced together this UDF from the many posts on the subject.
- xmlPath
- A URI to the XML file to be validated. Required.
- noNamespaceXsdUri
- A URI to the XML Schema file to validate content that is not namespace qualified. Optional.
-
- namespaceXsdUri
- A list of whitespace delimited namespaces and XSD URI pairs to provide schemas for validating namespace qualified content. Optional.
- parseError
- An empty structure that is populated with details about the validation error, if any. This argument can be ommitted if all you want is the boolean result.
The URI parameters must be valid URLs and not OS file names. To facilitate this I’m also including a UDF, makeUriFromPath, that convers a fully-qualified OS file name to a true URI.
To use this UDF you must have the Xerces parser installed which can be downloaded here.
var parser = createObject("java","org.apache.xerces.parsers.SAXParser");
var err = structNew();
var k = "";
var success = true;
var eHandler = createObject(
"java",
"org.apache.xml.utils.DefaultErrorHandler");
var apFeat = "http://apache.org/xml/features/";
var apProp = "http://apache.org/xml/properties/";
eHandler.init();
if (structKeyExists(arguments, "parseError")) {
err = arguments.parseError;
}
try {
parser.setErrorHandler(eHandler);
parser.setFeature(
"http://xml.org/sax/features/validation",
true);
parser.setFeature(
apFeat & "validation/schema",
true);
parser.setFeature(
apFeat & "validation/schema-full-checking",
true);
if (structKeyExists(arguments, "noNamespaceXsdUri") and
arguments.noNamespaceXsdUri neq "") {
parser.setProperty(
apProp & "schema/external-noNamespaceSchemaLocation",
arguments.noNamespaceXsdUri
);
}
if (structKeyExists(arguments, "namespaceXsdUri") and
arguments.namespaceXsdUri neq "") {
parser.setProperty(
apProp & "schema/external-schemaLocation",
arguments.namespaceXsdUri
);
}
parser.parse(arguments.xmlPath);
} catch (Any ex) {
structAppend(err, ex, true);
success = false;
}
function makeUriFromPath(path) {
var uri = path;
// make all backslashes into slashes
uri = replace(uri, "", "/", "all");
if (left(uri,1) is "/") {
uri = right(uri, len(uri) - 1);
}
uri = "file:///" & uri;
return uri;
}
Valid: #xsdValidate(xmlUri, xsdUri, "", err)#
This UDF was put together primarily from information in Rob Rohan’s post on this cf-talk thread and from Massimo Foti’s UDF to validate an XML file against a DTD.
I’ll submit both of the above to cflib shortly.