Xerces-C++ SAX2 Schema校验

1 篇文章 0 订阅

  经过几天的研究,终于完成了XML的SAX2 Schema校验。

  关于什么是Schema校验,在这里就不废话了,可以去google一下。

 下面我就把整个的过程写一下。


借用网上的一些XML文件。

store.xsd文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<!-- edited with XMLSpy v2011 (http://www.altova.com) by kevin (neuseeker) -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:element name="store">
        <xs:annotation>
            <xs:documentation>Comment describing your root element</xs:documentation>
        </xs:annotation>
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="goods" maxOccurs="unbounded"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="goods">
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="id"/>
                <xs:element ref="price"/>
                <xs:element ref="vendor"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
    <xs:element name="id" type="xs:string"/>
    <xs:element name="price" type="xs:double"/>
    <xs:element name="vendor" type="xs:string"/>
</xs:schema>
test_good.xml

<?xml version="1.0" encoding="utf-8"?>
<store>
    <goods>
        <id>"0001"</id>
        <price>3.50</price>
        <vendor>"xxx奶粉"</vendor>
    </goods>
    <goods>
        <id>"0002"</id>
        <price>66.00</price>
        <vendor>"yyy进口奶粉"</vendor>
    </goods>
</store>

test_bad.xml

<?xml version="1.0" encoding="utf-8"?>
<store>
    <goods>
        <id>"0001"</id>
        <price>3.50</price>
        <vendor>"xxx奶粉"</vendor>
        <name>"四路奶粉"</name>
    </goods>
    <goods>
        <id>"0002"</id>
        <price>"66.00"</price>
        <vendor>"yyy进口奶粉"</vendor>
    </goods>
</store>

以以上三个文件为例,进行验证。


代码如下:

OperContentHandler .hpp

#pragma  once

#if !defined(AFX_A1CONTENTHANDLER_H__E0CFBC18_CCC1_42F3_B0A4_B03331AB9693__INCLUDED_)
#define AFX_A1CONTENTHANDLER_H__E0CFBC18_CCC1_42F3_B0A4_B03331AB9693__INCLUDED_
#include "stdafx.h"
#include <xercesc\sax2\DefaultHandler.hpp>
#include <iostream>

using namespace std;

class  OperContentHandler :
	public DefaultHandler
{
public:
	OperContentHandler();
	virtual ~OperContentHandler();
	void characters
		(
		const   XMLCh* const    chars, 
		const XMLSize_t         length
		);
	void endElement
		(
		const XMLCh* const uri,
		const XMLCh* const localname,
		const XMLCh* const qname
		);

	virtual void startElement
		(
		const   XMLCh* const    uri,
		const   XMLCh* const    localname,
		const   XMLCh* const    qname
		, const Attributes&	attrs
		);

        // 继承自default Handle, 用于对错误的处理
	void error(const SAXParseException& exc)
	{
		throw exc;
	}
	void fatalError(const SAXParseException& exc)
	{
		throw exc;
	}
	void warning(const SAXParseException& exc)
	{
		throw exc;
	}

	wstring goods;

};
#endif // !defined(AFX_A1CONTENTHANDLER_H__E0CFBC18_CCC1_42F3_B0A4_B03331AB9693__INCLUDED_)

OperContentHandler.cpp


// OperContentHandler.cpp: derived class from SAXContentHandlerImpl

#include "stdafx.h"
#include "OperContentHandler.hpp"


//
// Construction/Destruction
//

OperContentHandler::OperContentHandler()
{
}

OperContentHandler::~OperContentHandler()
{
	//object destruction is handled by the Release() impl of parent class
}

void OperContentHandler::startElement
	(
	const   XMLCh* const    uri,
	const   XMLCh* const    localname,
	const   XMLCh* const    qname
	, const Attributes&	attrs
	)
{
	wstring	sNodeName = localname;
	goods += sNodeName;
}
void OperContentHandler::endElement( const XMLCh* const uri, 
	const XMLCh* const localname,
	const XMLCh* const qname )
{
	wstring	sNodeName = localname;
	goods += sNodeName;
}
void OperContentHandler::characters( const XMLCh* const chars, 
	const XMLSize_t length )
{
	wstring sNodeValue(chars);
	goods += sNodeValue;
}

SAXSchema.cpp文件

// SAXSchema.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "SAX2XMLReader.hpp"
#include "xercesc\sax2\XMLReaderFactory.hpp"
#include "OperContentHandler.hpp"
#include <stdio.h>
#include <string>

using namespace std;
using namespace xercesc_3_1; 

void memcpyEx(wchar_t* wDest, int iDsize, wstring src)
{
	size_t iCpy = src.length() + 1; // '\0'
	size_t iMax = iDsize/sizeof(wchar_t);

	if (src.empty())
	{
		memset(wDest, 0, iMax);
		return;
	}
	if (iCpy < iMax)
	{
		wmemset(wDest, 0, iMax);
		wmemcpy(wDest, src.c_str(), iCpy);
	}
	else
	{
		wmemset(wDest, '\0', iMax);
		iCpy = iMax - 1;
		wmemcpy(wDest, src.c_str(), iCpy);
	}
}

int _tmain(int argc, char* argv[])
{
	wchar_t *xmlPath = L"H:\\WorkSpace\\MarkupTest\\MarkupTest\\test_bad.xml";
	wchar_t *sxsdPath = L"H:\\WorkSpace\\MarkupTest\\MarkupTest\\store.xsd";

	OperContentHandler handler;
	wstring xsdPath(sxsdPath);
	try{
		XMLPlatformUtils::Initialize();
	}
	catch (...) {
		return 1;
	}

	SAX2XMLReader* parser = XMLReaderFactory::createXMLReader();
	parser->setFeature(XMLUni::fgSAX2CoreValidation, true);

	parser->setFeature(XMLUni::fgXercesSchema, true);
	parser->setFeature(XMLUni::fgXercesValidationErrorAsFatal, true);
	parser->setFeature(XMLUni::fgXercesContinueAfterFatalError, false);
	// 当Schema存在命名空间时,使用此部分;其中L"http://www.iec.ch/61850/2003/SCL "为我在试验时的一个命名空间
        //wstring xsd =  L"http://www.iec.ch/61850/2003/SCL " + xsdPath;
	//wchar_t xsdCh[400];
	//memcpyEx(xsdCh, sizeof(xsdCh), xsd);
	//parser->setProperty(XMLUni::fgXercesSchemaExternalSchemaLocation, xsdCh);
        
        // 当Schema不存在命名空间时,使用这个方法;在上述的XML中应该使用这个方法来设置模板文件
	parser->setProperty(XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation, sxsdPath);

        parser->setContentHandler(&handler);
	parser->setErrorHandler(&handler);

	try
	{
		parser->parse(xmlPath); 
	}
	catch (const SAXParseException& toCatch) 
	{ 
		int iCol = toCatch.getColumnNumber();
		int iRow = toCatch.getLineNumber();

		wchar_t cCol[10], cRow[10]; 
		_itow(iCol, cCol, 10); 
		_itow(iRow, cRow, 10);
		wstring sCol(cCol);
		wstring sRow(cRow);

		wstring sMes(toCatch.getMessage());
                // 此处将展示错误信息
                wstring wValue = L"行:" + sRow + L",列:" + sCol+ L"  " + sMes;
		return 0; 
	}
	catch (const OutOfMemoryException &ome)
	{
		wstring sMes(ome.getMessage());
		return false; 
	}
	catch (const XMLException &xe)
	{
		wstring sMes(xe.getMessage());
		return false; 
	}

	delete parser;
	XMLPlatformUtils::Terminate();
	return 0;
}


当进行校验完成后,在wValue的值为:行:7,列:9  no declaration found for element 'name'


上面就是整个Schema校验的校验过程,注意点主要为一下:

一,

在上述的OperContentHandler中,我们重写了继承自DefaultHandler的三个错误处理方法。如果不重写这些方法,OperContentHandler则只是处理了解析过程中和文档内容相关的事件。如果不注册一个错误处理器来处理的话,那么错误事件将不会被报告,而且解析器会出现不可预知的行为。在解析过程中产生的错误被分成了3类,它们分别是warning,error,以及fatalerror,也就是说在ErrorHandler中有这么三个相应的方法来处理这些错误事件。

二,

通过设置fgXercesSchemaExternalNoNameSpaceSchemaLocation或者fgXercesSchemaExternalSchemaLocation属性来设置XSD文件;之前一直以为可以通过loadGrammar()来进行XSD的设置,但是总是不行,可能是理解不到位,不会使用。所以改成了设置属性这种方法。


参考文献:

1,http://www.cnblogs.com/kevin_neu/archive/2013/04/16/3003514.html

2,http://www.codeproject.com/Articles/11085/Parsing-XML-using-a-C-wrapper-for-SAX2

3,http://www.ibm.com/developerworks/cn/xml/x-xsdxerc.html

4,http://xerces.apache.org/xerces-c/program-sax2-3.html

5,https://www.ibm.com/developerworks/cn/xml/x-saxhandle/




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值