验证未使用Xerces定义架构的XML

时间:2010-12-07 09:45:20

标签: c++ xml xsd xerces

我正在使用Xerces-C ++(版本2.6.1)SAX2解析器来验证XML,例如下面的文档。 (这是MSML - 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>

RFC提供XML schemas for validating MSML,我正在尝试将它们与Xerces SAX2解析器结合使用来验证和解析MSML。解析工作正常,但我没有得到任何验证。我怀疑我的问题可能是因为我试图验证的MSML不包含schemaLocation属性,但我无法控制我收到的XML - 我想强制使用msml.xsd验证是否XML中提供了schemaLocationnoNamespaceSchemaLocation(或没有)。

我的代码类似于以下内容。

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);

// 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);

1 个答案:

答案 0 :(得分:2)

随着周围的反复试验和错误,我最终发现了问题。验证错误会报告给传递给解析器的error上的ErrorHandler回调。 schemaLocation属性没有问题。

通过修复,并添加XML语法的缓存以提高性能,代码现在如下。

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);