⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xml_parser.cpp

📁 一个通过远程给制定的数据库进行远程备份的源代码~~
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/////////////////////////////////////////////////////////////////////////
// 类名:XML_PARSER
// 功能:XML文件读写、解析包装类
// 附注:简化编程工作量
// 修订:徐景周(jingzhou_xu@163.com)
// 组织:Future Studio
// 日期:2005.5.9
// What's news ?
// 
//      1. The parsing document start from document and not from root element
//           - Let us to parse the header document informations
//      2. New XML header management
//           - encoding format, stylesheet reference, etc...
//                - Set_Header("xml","version","1.0")
//                - Set_Header("xml","encoding","UTF-8"), etc...
//      3. New CData section management 
//           - We can now read and add CData section with method like "Add_LastChildCData(LPCTSTR data)"
//      4. Some new methods for more fun
//           - like "Get_XML_Document()"
//      5. Minor design change for improve the class
//           - Some methods have been renamed like "Get_Text()" to "Get_TextValue()"
//      
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include <stdafx.h>
#include <atlbase.h>
#include "XML_PARSER.h"

//using namespace MSXML2;		// 为避免于老版本名字空间冲突,改为导入老版本,jingzhou xu,2005.5.17

XML_PARSER::XML_PARSER()
{       // Constructor

        // Init our members
        //
        this->AttribNames.RemoveAll();
        this->AttribValues.RemoveAll();
        this->Tag.Empty();
        this->Name.Empty();
        this->ChainTag.Empty();
        this->TextField.Empty();

        // Init MSXML members
        //
        CurrentNode		= NULL;
        m_plDomDocument = NULL;
        m_pDocRoot		= NULL;

        attrib_index	= -1;

        // -- Errors Init --
        //
        ok.Empty();
        ok				= "Success";
        lasterror		= ok;
}

XML_PARSER::~XML_PARSER()
{       // Free ressource
        //
        this->Reset_XML_Document();
}

CString & XML_PARSER::Get_LastError()
{ return lasterror; }

bool XML_PARSER::Init_MSXML()
{      
		lasterror = ok;

        // -- Init OLE Object Comunication for MSXML (only once time)--
        //
        static bool ole_initialized = false;
        if( !ole_initialized )
        {       
			::AfxOleInit();					// 初始化
            ole_initialized = true;
        }

        // -- Instantiate an XML document --
        //
        HRESULT hr = m_plDomDocument.CreateInstance(MSXML::CLSID_DOMDocument);
        if( FAILED(hr) )
        {       
			_com_error er(hr);
            lasterror = er.ErrorMessage();
            return false;
        }

        return true;
}

bool XML_PARSER::Load_XML_Document(LPCTSTR strFileName)
{ 
		lasterror = ok;

        // Reset Document
        //
        this->Reset_XML_Document();

        // Convert xml file name string to something COM can handle (BSTR)
        //
        CString sFileName = strFileName;
        _bstr_t bstrFileName;
        bstrFileName = sFileName.AllocSysString();

        // Call the IXMLDOMDocumentPtr's load function to load the XML document
        //
        variant_t vResult;
        vResult = m_plDomDocument->load(bstrFileName);
        if( ((bool)vResult) == TRUE ) // success!
        {
                // Now that the document is loaded, we need to initialize the root pointer
                //
                m_pDocRoot = m_plDomDocument->documentElement;

                // Now we can Parse this document !!
                //
                Parse_Objects(m_plDomDocument);

                this->Go_to_Root();

                return true;
        }
        else
        {       // XML document is not loaded, return error
                //
                lasterror = "XML Document FAILED to load";
                return false;
        }
}

void XML_PARSER::Load_XML_From_Buffer(LPCTSTR source)
{
        // Reset the document
        //
        this->Reset_XML_Document();

        // Load from Buffer
        //
        m_plDomDocument->loadXML(source);
        m_pDocRoot = m_plDomDocument->documentElement;

        // Start the Parsing
        //
        Parse_Objects(m_plDomDocument);

        // Move to the root node
        //
        this->Go_to_Root();
}

void XML_PARSER::Get_XML(CString & buffer)
{       
        if(this->CurrentNode == this->m_pDocRoot)
            this->Get_XML_Document(buffer);
        else
        {   BSTR  b_xml;
            this->CurrentNode->get_xml(&b_xml);

            buffer = b_xml;
        }
}

void XML_PARSER::Get_XML_Document(CString & buffer)
{   
	BSTR b_xml;
    this->m_plDomDocument->get_xml(&b_xml);

    buffer = b_xml;
}

bool XML_PARSER::Parse_XML_Document()
{ 
	/* Nothing to do , this method will be redefined in derived class */ 
	return false;
}

void XML_PARSER::Parse_Objects(MSXML::IXMLDOMNodePtr pObject)
{
        // Child node
        //
        MSXML::IXMLDOMNodePtr pChild;

        // Grab Informations from the pObject node
        //
        this->Grab_Node_Informations(pObject);

        // Update "CurrentNode"
        //
        this->CurrentNode = pObject;

        // Call User Parse Handling for let him what he want.
        //
        this->Parse_XML_Document();

        if(Is_MSXML_Node(pObject) != MSXML::NODE_ELEMENT)
           return;

        // add the ChainTag
        //
        this->ChainTag_Add(this->Tag);

        for (pChild = pObject->firstChild;  NULL != pChild;  pChild = pChild->nextSibling)
        {
                // Parse Child nodes
                //
                this->Parse_Objects(pChild);
        }

        // Remove Current Tag from ChainTag
        //
        ChainTag_Remove(1);
}

bool XML_PARSER::Is_Tag(LPCTSTR aTag)
{ 
	return this->Get_CurrentTag() == aTag; 
}

bool XML_PARSER::Is_TextNode()
{ 
	return (this->Is_Tag("<#TEXT#>")); 
}

bool XML_PARSER::Is_CDataSection()
{ 
	return (this->Is_Tag("<#CDATA#>")); 
}

CString & XML_PARSER::Get_CurrentTag()
{       return this->Tag; }

CString & XML_PARSER::Get_CurrentName()
{  
	return this->Name; 
}

bool XML_PARSER::Is_Root()
{   
	return (this->ChainTag.IsEmpty() != 0); 
}

bool XML_PARSER::Is_Child_of(LPCTSTR parent_chain)
{
        int pos = this->ChainTag.Find(parent_chain);
        int len = strlen(parent_chain);

        if(pos != -1)
        {       // look if it's the end of this chainTag
                //
                return ( this->ChainTag.GetLength() == pos + len );
        }

        return false;
}

CString & XML_PARSER::Get_TextValue()
{  // Now you can handle the text value on the real node directly if you want

   if(Is_MSXML_Node(this->CurrentNode) == MSXML::NODE_TEXT || Is_MSXML_Node(this->CurrentNode) == MSXML::NODE_CDATA_SECTION)
      return this->TextField;

   // We must find his text value
   //
   CString TextValue;

   // Find if a CHILD TEXT NODE exist or not
   //
   if(CurrentNode == NULL)
   {       if(this->m_pDocRoot != NULL)
                   this->CurrentNode = this->m_pDocRoot;
           else
           {       // We can't set the text
                   //
                   lasterror = "XML_PARSER::Get_TextValue() Can't set text on NULL node";
                   this->TextField = "";
                   return this->TextField;
           }
   }

   // Find it now
   //
   if(this->CurrentNode->hasChildNodes())
   {
           MSXML::IXMLDOMNodePtr pChild;
           for(pChild = this->CurrentNode->firstChild; pChild != NULL; pChild = pChild->nextSibling)
           {       // Find it's a NODE TEXT
                   //
                   if(this->Is_MSXML_Node(pChild) == MSXML::NODE_TEXT)
                   {       // Take informations from this Text Node
                           //
                           this->Grab_Node_Informations(pChild);
                           TextValue = this->TextField;
                           this->Grab_Node_Informations(this->CurrentNode); // it remove this->TextField
                           this->TextField = TextValue;
                           return (this->TextField);
                   }
           }
   }

   this->TextField = "";
   return (this->TextField);
}

HRESULT XML_PARSER::Is_MSXML_Node(MSXML::IXMLDOMNodePtr pChild)
{ 
	if(pChild == NULL) return NULL;

        // I handle only few node type other are ignored and are considered as NODE_ELEMENT
        //
        // Handled Node type by this wrapper:
        //      - NODE_ELEMENT
        //      - NODE_TEXT
        //      - NODE_CDATA_SECTION
        //      - NODE_PROCESSING_INSTRUCTION

        if(pChild->nodeType == MSXML::NODE_TEXT) return MSXML::NODE_TEXT;
        if(pChild->nodeType == MSXML::NODE_CDATA_SECTION) return MSXML::NODE_CDATA_SECTION;
        if(pChild->nodeType == MSXML::NODE_PROCESSING_INSTRUCTION ) return MSXML::NODE_PROCESSING_INSTRUCTION;
        return MSXML::NODE_ELEMENT;
}

void XML_PARSER::Grab_Node_Informations(MSXML::IXMLDOMNodePtr pChild)
{
        if(this->Is_MSXML_Node(pChild) == MSXML::NODE_ELEMENT)
        {       // It's a node
                //

                // Tag Update
                //
                Tag.Format("<%s>",(const char*)(pChild->nodeName));
                Name = (const char*)(pChild->nodeName);

                // TextField no significant value
                TextField.Empty();

                // Update Attribute List
                //
                this->AttribNames.RemoveAll();
                this->AttribValues.RemoveAll();

                MSXML::IXMLDOMNamedNodeMapPtr pAttribs = pChild->Getattributes();
                if(pAttribs != NULL)
                {       long nAttriCnt = pAttribs->Getlength();
                        // Iterate over the attributes
                        //
                        for(int i=0; i<nAttriCnt; ++i)
                        {  MSXML::IXMLDOMNodePtr pAttrib = pAttribs->Getitem(i);
                           if(pAttrib != NULL)
                           {
                              this->AttribNames.Add(  (CString)(const char *) pAttrib->GetnodeName() );

                              _variant_t vVal = pAttrib->GetnodeValue ( );
                              this->AttribValues.Add( (CString)(const char *) _bstr_t(vVal) );
                           }
                        }
                }
        }
        else if (this->Is_MSXML_Node(pChild) == MSXML::NODE_TEXT)
        {   // Tag is #TEXT#
            //
            Tag.Empty();
            Tag = "<#TEXT#>";
            Name.Empty();
            Name = "#TEXT#";

            // TextField Update
            //
            TextField = (const char*)(pChild->text);

            // Update Attribute List have no means
            //
            this->AttribNames.RemoveAll();
            this->AttribValues.RemoveAll();
        }
        else if (this->Is_MSXML_Node(pChild) == MSXML::NODE_CDATA_SECTION)
        {   // Tag is #CDATA#
            //
            Tag.Empty();
            Tag = "<#CDATA#>";
            Name.Empty();
            Name = "#CDATA#";

            // TextField Update
            //
            TextField = (const char*)(pChild->text);

            // Update Attribute List have no means
            //
            this->AttribNames.RemoveAll();
            this->AttribValues.RemoveAll();
        }
        else if (this->Is_MSXML_Node(pChild) == MSXML::NODE_PROCESSING_INSTRUCTION)
        {  /* Do nothing here */ } 

        return;
}

void XML_PARSER::ChainTag_Add(CString & val)
{
        // Add a tag to the ChainTag
        //
        if(!ChainTag.IsEmpty())
           ChainTag += val;
        else
           ChainTag = val;
}

void XML_PARSER::ChainTag_Remove(int number)
{
        // Remove the n tag to the ChainTag
        //
        for(int bcl = 0; bcl < number; bcl ++)
        {
           int pos = ChainTag.ReverseFind('<');
           if(pos == -1)
              ChainTag.Empty();
           else
              ChainTag = ChainTag.Left(pos);
        }
}

int XML_PARSER::Get_Attribute_Count()
{ 
	return this->AttribNames.GetSize(); 
}

CString & XML_PARSER::Get_Attribute_Name(int index)
{ 
	lasterror = "XML_PARSER::Get_Attribute_Name(int) failed";

   if(index < 0 || index > this->Get_Attribute_Count())
   {    tmp.Empty();
        return tmp;
   }

   lasterror = ok;
   return this->AttribNames[index]; 
}

CString & XML_PARSER::Get_Attribute_Value(int index)
{
	lasterror = "XML_PARSER::Get_Attribute_Value(int) failed";

   if(index < 0 || index > this->Get_Attribute_Count())
   {    tmp.Empty();
        return tmp;
   }

   lasterror = ok;
   return this->AttribValues[attrib_index];
}

bool XML_PARSER::Is_Having_Attribute(LPCTSTR Name)
{
   // Create the CString Name Object
   //
   CString sName = Name;
                
   // Clear attribute index
   //
   attrib_index = -1;

   int bcl;
   for(bcl = 0; bcl < this->Get_Attribute_Count() ; bcl++)
   {  // Check if the name is equal
      //
      if(this->AttribNames[bcl] == sName)
      {  // set index fot let user to retrieve value with "Get_Attribute_Value()" method
         //
         attrib_index = bcl;
         return true;
      }
   }
   return false;
}

CString & XML_PARSER::Get_Attribute_Value()
{  // Assume Success
   //
   lasterror = ok;

   if(attrib_index != -1)
         return this->AttribValues[attrib_index];

   // We can't retrieve a Attribute values
   //
   lasterror = "XML_PARSER::Get_Attribute_Value()  : Can't Retrieve an Attribute";
   return lasterror;
}

bool XML_PARSER::_add_lastchild(MSXML::IXMLDOMNodePtr newNode)
{       // Attach the Node to the document
        //
        if(CurrentNode != NULL)
        {       if(Is_MSXML_Node(this->CurrentNode) != MSXML::NODE_ELEMENT) return false;
                this->ChainTag_Add( this->Get_CurrentTag() );
                newNode = CurrentNode->appendChild(newNode);
        }
        else if(m_pDocRoot != NULL)
        {       if(Is_MSXML_Node(this->m_pDocRoot) != MSXML::NODE_ELEMENT) return false;
                this->ChainTag_Add( (CString)(const char*)m_pDocRoot->nodeName );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -