#include "StdAfx.h"
#include "ExpatXmlParser.h"

CExpatXmlParser::CExpatXmlParser(void)
{
	m_init = FALSE;
}

CExpatXmlParser::~CExpatXmlParser(void)
{
	Close();
}



/////////////////////////////////////////////////////////////////////////////////////
//	開始
/////////////////////////////////////////////////////////////////////////////////////
/*!
	ファイルから取得
*/
void CExpatXmlParser::ScanXmlFile(CString path)
{
	//	開く
	CBinaryData	load;
	if(load.LoadFromFile(path))
		throw CXMLTextParserException(_T("ファイルのオープンに失敗しました"));

	StartScan(load);
}


/*!
	スキャン
*/
void CExpatXmlParser::StartScan(CBinaryData &xml)
{
	//	初期化
	if(Init())
		throw CXMLTextParserException(_T("XMLパーサーの初期化に失敗しました"));

	//	解析
	if(XML_Parse(m_parser, (const XML_Char*)xml.GetPtr(), (int)xml.GetSize(), TRUE) != XML_TRUE)
		throw CXMLTextParserException(_T("XMLの解析に失敗しました"));
}


/////////////////////////////////////////////////////////////////////////////////////
//	補助
/////////////////////////////////////////////////////////////////////////////////////
/*!
	初期化
*/
int CExpatXmlParser::Init()
{
	if(!m_init)
	{
		//	初期化
		m_parser = XML_ParserCreateNS(NULL, 0);
		if(m_parser == NULL)
			return(-1);

		//	ユーザーデータセット
		XML_SetUserData(m_parser, this);

		//	ハンドラセット
		XML_SetElementHandler(m_parser, StartElementHandler, EndElementHandler);
		XML_SetCharacterDataHandler(m_parser, CharacterDataHandler);
		XML_SetNamespaceDeclHandler(m_parser, StartNamespaceDeclHandler, EndNamespaceDeclHandler);
		m_init = TRUE;
	}
	else
	{
		//	リセット
		if(XML_ParserReset(m_parser, NULL) != XML_TRUE)
			return(-1);
	}
	return(0);
}

/*!
	終了
*/
void CExpatXmlParser::Close()
{
	if(m_init)
	{
		XML_ParserFree(m_parser);
	}
	m_init = FALSE;
}


/*!
	Attr数チェック
*/
int CExpatXmlParser::GetAttrCount(const XML_Char **atts)
{
	//	数える
	int i;
	for(i=0;atts[i];i++)
		;
	return(i);
}


/////////////////////////////////////////////////////////////////////////////////////
//	コールバック
/////////////////////////////////////////////////////////////////////////////////////
/*!
	開始タグ
*/
void CExpatXmlParser::StartElementHandler(void *userData, const XML_Char *name, const XML_Char **atts)
{
	CExpatXmlParser *obj = (CExpatXmlParser*)userData;

	//	コール
	obj->OnStartTag(name, atts, CExpatXmlParser::GetAttrCount(atts));
}

/*!
	終了タグ
*/
void CExpatXmlParser::EndElementHandler(void *userData, const XML_Char *name)
{
	CExpatXmlParser *obj = (CExpatXmlParser*)userData;

	//	コール
	obj->OnEndTag(name);
}

/*!
	データ
*/
void CExpatXmlParser::CharacterDataHandler(void *userData, const XML_Char *s, int len)
{
	CExpatXmlParser *obj = (CExpatXmlParser*)userData;

	//	コール
	obj->OnData((const char*)s, len);
}


/*!
	ネームスペース開始
*/
void CExpatXmlParser::StartNamespaceDeclHandler(void *userData,  const XML_Char *prefix, const XML_Char *uri)
{
	CExpatXmlParser *obj = (CExpatXmlParser*)userData;

	//	コール
	obj->OnStartNS((const char*)prefix, (const char*)uri);
}

/*!
	ネームスペース終了
*/
void CExpatXmlParser::EndNamespaceDeclHandler(void *userData,  const XML_Char *prefix)
{
	CExpatXmlParser *obj = (CExpatXmlParser*)userData;

	//	コール
	obj->OnEndNS((const char*)prefix);
}
