用xerces-c来进行xml schema校验

在xerces-c的官方网站上有文章指引说明是如何进行xml schema校验。http://xerces.apache.org/xerces-c/schema-3.html

给出的例子代码:

// Instantiate the DOM parser.
XercesDOMParser parser;
parser.setDoNamespaces(true);
parser.setDoSchema(true);
parser.parse(xmlFile);

但,例子代码根本不起任何作用。

在调用XercesDOMParser::parse之前,还有两件事情要做:

1.调用XercesDOMParser::setValidationScheme来设置校验计划

parser.setValidationScheme( XercesDOMParser::Val_Auto);

parser.setValidationScheme( XercesDOMParser::Val_Always);

2.要调用XercesDOMParser::setErrorHandler, 其中参数必须是ErrorHandler类或子类的对象。


看下面例子

address.xml:

<?xml version="1.0" encoding="utf-8"?>
<Address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:noNamespaceSchemaLocation="address.xsd">
	<Recipient>Mr. Walter C. Brown</Recipient>
	<House>good</House>
	<Street>Featherstone Street</Street>
	<Town>LONDON</Town>
	<PostCode>EC1Y 8SY</PostCode>
	<Country>UK</Country>
</Address>

address.xsd:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
	<xs:element name="Address">
		<xs:complexType>
			<xs:sequence>
				<xs:element name="Recipient" type="xs:string" />
				<xs:element name="House" type="xs:string" />
				<xs:element name="Street" type="xs:string" />
				<xs:element name="Town" type="xs:string" />
				<xs:element name="County" type="xs:string" minOccurs="0" />
				<xs:element name="PostCode" type="xs:unsignedInt" />
				<xs:element name="Country" minOccurs="0">
					<xs:simpleType>
						<xs:restriction base="xs:string">
							<xs:enumeration value="IN" />
							<xs:enumeration value="DE" />
							<xs:enumeration value="ES" />
							<xs:enumeration value="UK" />
							<xs:enumeration value="US" />
						</xs:restriction>
					</xs:simpleType>
				</xs:element>
			</xs:sequence>
		</xs:complexType>
	</xs:element>
</xs:schema>

new_address.cpp:

#include <stdio.h>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/sax/SAXException.hpp>
#include <xercesc/dom/DOMException.hpp>
#include <xercesc/dom/DOMElement.hpp>
#include <xercesc/dom/DOMLSException.hpp>
#include <xercesc/sax2/DefaultHandler.hpp>

using namespace XERCES_CPP_NAMESPACE;

class SchemaErrorHandler : public DefaultHandler
{
	public:
		SchemaErrorHandler() {}
		~SchemaErrorHandler() {}

	void warning(const SAXParseException& exc)
	{
		printf( "warn in line:%lu, col:%lu, %s\n", 
				exc.getLineNumber(), exc.getColumnNumber(),
				XMLString::transcode( exc.getMessage()) );
	}

    void error(const SAXParseException& exc)
	{
		printf( "error in line:%lu, col:%lu, %s\n", 
				exc.getLineNumber(), exc.getColumnNumber(),
				XMLString::transcode( exc.getMessage()) );
	}

    void fatalError(const SAXParseException& exc)
	{
		printf( "fatal in line:%lu, col:%lu, %s\n", 
				exc.getLineNumber(), exc.getColumnNumber(),
				XMLString::transcode( exc.getMessage()) );
	}

    void resetErrors()
	{
		printf( "nothing\n" );
	}
};

int main(int argc, char* argv[] )
{
	if ( argc < 2 )
	{
		printf( "must specify a file\n" );
		return -1;
	}

	XMLPlatformUtils::Initialize();

	XercesDOMParser parser;
	SchemaErrorHandler handler;
	try
	{
		parser.setErrorHandler( &handler );
		parser.setDoNamespaces(true);
		parser.setDoSchema(true);
		//parser.setValidationScheme( XercesDOMParser::Val_Auto);
		parser.parse( argv[1] );
	} catch ( SAXException& e )
	{
		printf( "msg:%s\n", XMLString::transcode(e.getMessage() ) );
		return -2;
	}
	catch ( XMLException& e )
	{
		printf( "code:%d, msg:%s\n", e.getCode(), XMLString::transcode( e.getMessage() ) );
		return -3;
	}
	catch (	DOMException& e )
	{
		printf( "code:%d, msg:%s\n", e.code, e.msg );
		return -4;
	}

	return 0;
}
可以看到这里的代码注释掉了这一行:

//parser.setValidationScheme( XercesDOMParser::Val_Auto);


编译运行:

[xuzhina@localhost sample]$ g++ -g -o new_address new_address.cpp -lxerces-c
[xuzhina@localhost sample]$ ./new_address address.xml 
[xuzhina@localhost sample]$ 

//parser.setValidationScheme( XercesDOMParser::Val_Auto);
打开,但注释掉

parser.setErrorHandler( &handler );
编译运行:

[xuzhina@localhost sample]$ g++ -g -o new_address new_address.cpp -lxerces-c
[xuzhina@localhost sample]$ ./new_address address.xml 
[xuzhina@localhost sample]$ 

parser.setErrorHandler( &handler );

打开,编译运行:

[xuzhina@localhost sample]$ ./new_address address.xml 
error in line:8, col:31, value 'EC1Y 8SY' does not match regular expression facet '[+\-]?[0-9]+'

运行一下xmllint,对比一下结果:

[xuzhina@localhost sample]$ xmllint --schema address.xsd address.xml
<?xml version="1.0" encoding="utf-8"?>
<Address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="address.xsd">
	<Recipient>Mr. Walter C. Brown</Recipient>
	<House>good</House>
	<Street>Featherstone Street</Street>
	<Town>LONDON</Town>
	<PostCode>EC1Y 8SY</PostCode>
	<Country>UK</Country>
</Address>
address.xml:8: element PostCode: Schemas validity error : Element 'PostCode': 'EC1Y 8SY' is not a valid value of the atomic type 'xs:unsignedInt'.
address.xml fails to validate

PS:

在xml schema中,string是兼容其它类型,比如在House标签的内容写上数字,比如49,无论xmllint, 还是xerces都不会报这个标签的值有问题。曾经为这个问题折腾一个下午。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果您的 Xerces-C 库在进行大文件校验时崩溃,可能是因为它尝试将整个文件加载到内存中进行处理,导致内存不足。为了解决这个问题,您可以使用 Xerces-C 的 SAX 接口来处理 XML 文件。SAX 接口允许您在处理 XML 文件时逐个节点处理,而不是将整个文件加载到内存中。 以下是使用 SAX 接口进行 XSD 校验的示例代码: ```c++ #include <iostream> #include <xercesc/sax/HandlerBase.hpp> #include <xercesc/parsers/XercesDOMParser.hpp> #include <xercesc/framework/LocalFileInputSource.hpp> #include <xercesc/framework/XMLValidator.hpp> #include <xercesc/util/XMLString.hpp> using namespace xercesc; class XSDValidator : public HandlerBase { public: void startElement( const XMLCh* const uri, const XMLCh* const localname, const XMLCh* const qname, const Attributes& attrs ) { // Add your validation logic here } }; int main() { XMLPlatformUtils::Initialize(); XercesDOMParser parser; parser.setValidationScheme(XercesDOMParser::Val_Always); parser.setDoNamespaces(true); XSDValidator handler; parser.setErrorHandler(&handler); parser.setDocumentHandler(&handler); LocalFileInputSource source(XMLString::transcode("your_file.xml")); parser.parse(source); XMLPlatformUtils::Terminate(); return 0; } ``` 在上面的示例中,我们使用 Xerces-C 的 SAX 接口来处理 XML 文件。我们创建了一个名为 `XSDValidator` 的处理程序,它实现了 `HandlerBase` 接口并重写了 `startElement` 方法来添加自己的验证逻辑。在 `main` 函数中,我们创建了一个 `XercesDOMParser` 对象,并将其配置为始终进行验证。然后,我们将 `XSDValidator` 处理程序分配给 `parser` 对象,并使用 `LocalFileInputSource` 对象来指定要验证的 XML 文件。最后,我们调用 `parse` 方法来开始解析文件。 请注意,在上面的示例中,我们没有将整个文件加载到内存中。相反,我们使用 SAX 接口逐个节点处理 XML 文件,从而避免了内存不足的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值