Validating XML that doesn't define a schema using Xerces
I'm using the Xerces-C++ (version 2.6.1) SAX2 parser to validate XML such as the document below. (This is MSML - Media Server Markup Language as defined in RFC 5707.)
<?xml version="1.0" encoding="UTF-8"?>
<msml version="1.1">
<createconference name="example">
<audiomix>
<n-loudest n="3"/>
<asn ri="10s"/>
</audiomix>
</createconference>
</msml>
The RFC provides XML schemas for validating MSML, and I'm trying to use them in conjunction with the Xerces SAX2 parser to validate and parse MSML. The parsing is working fine, but I'm failing to get any validation. I suspect my problem might be because the MSML I'm trying to validate doesn't include a schemaLocation
attribute, but I can't control what XML I receive - I would like to force validation using the msml.xsd whether schemaLocation
or noNamespaceSchemaLocation
(or nothing) is provided in the XML.
My code is similar to the following.
SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();
// Enable the parser's schema support
parser->setFeature(XMLUni::fgXercesSchema, true);
// Schema validation requires namespace processing to be turned on.
parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
parser->setFeature(XMLUni::fgSAX开发者_运维百科2CoreNameSpaces, true);
// Define the location of the MSML schema.
XMLCh* schemaLocation = XMLString::transcode("/directory/path/msml-core.xsd");
parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation,
schemaLocation);
// MSMLHandler is defined elsewhere and inherits from xercesc/sax2/DefaultHandler
// It overrides startElement and fatalError.
MxMSMLHandler* msmlHandler = new MSMLHandler(xiSessionID, xoMSMLResponse);
parser->setContentHandler((ContentHandler*) msmlHandler);
parser->setErrorHandler((ErrorHandler*) msmlHandler);
// Do the parse
parser->parse(*xmlInputSource);
And with much flailing around and trial and error, I eventually found the problems. Validation errors are reported to the error
callback on the ErrorHandler
passed to the parser. There was no problem with the schemaLocation
attribute.
With that fixed, and adding in caching of the XML grammar to improve performance, the code is now as follows.
SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();
// Enable the parser's schema support
parser->setFeature(XMLUni::fgXercesSchema, true);
// Schema validation requires namespace processing to be turned on.
parser->setFeature(XMLUni::fgSAX2CoreValidation, true);
parser->setFeature(XMLUni::fgSAX2CoreNameSpaces, true);
// Cache the XML grammar and use it for subsequent parses.
mParser->setFeature(XMLUni::fgXercesCacheGrammarFromParse, true);
mParser->setFeature(XMLUni::fgXercesUseCachedGrammarInParse, true);
// Define the location of the MSML schema.
XMLCh* schemaLocation = XMLString::transcode("/directory/path/msml-core.xsd");
parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation,
schemaLocation);
// MSMLHandler is defined elsewhere and inherits from xercesc/sax2/DefaultHandler
// It overrides startElement, fatalError *and error*.
MxMSMLHandler* msmlHandler = new MSMLHandler(xiSessionID, xoMSMLResponse);
parser->setContentHandler((ContentHandler*) msmlHandler);
parser->setErrorHandler((ErrorHandler*) msmlHandler);
// Do the parse
parser->parse(*xmlInputSource);
精彩评论