Back to index

lightning-sunbird  0.9+nobinonly
ParseExpat.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 
00003 #define XML_UNICODE
00004 #include "xmlparse.h"
00005 
00006 #ifdef XML_UNICODE
00007 #define X2OLE W2COLE
00008 #define X2T W2T
00009 #else
00010 #define X2OLE A2COLE
00011 #define X2T A2T
00012 #endif
00013 
00014 
00015 struct ParserState
00016 {
00017        CComQIPtr<IXMLDocument, &IID_IXMLDocument> spXMLDocument;
00018        CComQIPtr<IXMLElement, &IID_IXMLElement> spXMLRoot;
00019        CComQIPtr<IXMLElement, &IID_IXMLElement> spXMLParent;
00020 };
00021 
00022 static ParserState cParserState;
00023 
00024 
00025 // XML data handlers
00026 static void OnStartElement(void *userData, const XML_Char *name, const XML_Char **atts);
00027 static void OnEndElement(void *userData, const XML_Char *name);
00028 static void OnCharacterData(void *userData, const XML_Char *s, int len);
00029 static void OnDefault(void *userData, const XML_Char *s, int len);
00030 
00031 
00032 struct ParseData
00033 {
00034        CComQIPtr<IXMLDocument, &IID_IXMLDocument> spDocument;
00035        CComQIPtr<IXMLElement, &IID_IXMLElement> spRoot;
00036 };
00037 
00038 HRESULT ParseExpat(const char *pBuffer, unsigned long cbBufSize, IXMLDocument *pDocument, IXMLElement **ppElement)
00039 {
00040        if (pDocument == NULL)
00041        {
00042               return E_INVALIDARG;
00043        }
00044 
00045        XML_Parser parser = XML_ParserCreate(NULL);
00046        HRESULT hr = S_OK;
00047 
00048        cParserState.spXMLDocument = pDocument;
00049        pDocument->get_root(&cParserState.spXMLParent);
00050 
00051        // Initialise the XML parser
00052        XML_SetUserData(parser, &cParserState);
00053 
00054        // Initialise the data handlers
00055        XML_SetElementHandler(parser, OnStartElement, OnEndElement);
00056        XML_SetCharacterDataHandler(parser, OnCharacterData);
00057        XML_SetDefaultHandler(parser, OnDefault);
00058 
00059        // Parse the data
00060        if (!XML_Parse(parser, pBuffer, cbBufSize, 1))
00061        {
00062               /* TODO Create error code
00063                  fprintf(stderr,
00064                      "%s at line %d\n",
00065                  XML_ErrorString(XML_GetErrorCode(parser)),
00066                  XML_GetCurrentLineNumber(parser));
00067                */
00068               hr = E_FAIL;
00069        }
00070 
00071        // Cleanup
00072        XML_ParserFree(parser);
00073 
00074        cParserState.spXMLRoot->QueryInterface(IID_IXMLElement, (void **) ppElement);
00075        cParserState.spXMLDocument.Release();
00076        cParserState.spXMLParent.Release();
00077 
00078        return S_OK;
00079 }
00080 
00081 
00083 
00084 
00085 void OnStartElement(void *userData, const XML_Char *name, const XML_Char **atts)
00086 {
00087        ParserState *pState = (ParserState *) userData;
00088        if (pState)
00089        {
00090               USES_CONVERSION;
00091 
00092               CComQIPtr<IXMLElement, &IID_IXMLElement> spXMLElement;
00093 
00094               // Create a new element
00095               pState->spXMLDocument->createElement(
00096                             CComVariant(XMLELEMTYPE_ELEMENT),
00097                             CComVariant(X2OLE(name)),
00098                             &spXMLElement);
00099 
00100               if (spXMLElement)
00101               {
00102                      // Create each attribute
00103                      for (int i = 0; atts[i] != NULL; i += 2)
00104                      {
00105                             const XML_Char *pszName = atts[i];
00106                             const XML_Char *pszValue = atts[i+1];
00107                             spXMLElement->setAttribute((BSTR) X2OLE(pszName), CComVariant(X2OLE(pszValue)));
00108                      }
00109 
00110                      if (pState->spXMLRoot == NULL)
00111                      {
00112                             pState->spXMLRoot = spXMLElement;
00113                      }
00114                      if (pState->spXMLParent)
00115                      {
00116                             // Add the element to the end of the list
00117                             pState->spXMLParent->addChild(spXMLElement, -1, -1);
00118                      }
00119                      pState->spXMLParent = spXMLElement;
00120               }
00121        }
00122 }
00123 
00124 
00125 void OnEndElement(void *userData, const XML_Char *name)
00126 {
00127        ParserState *pState = (ParserState *) userData;
00128        if (pState)
00129        {
00130               CComQIPtr<IXMLElement, &IID_IXMLElement> spNewParent;
00131               if (pState->spXMLParent)
00132               {
00133                      pState->spXMLParent->get_parent(&spNewParent);
00134                      pState->spXMLParent = spNewParent;
00135               }
00136        }
00137 }
00138 
00139 
00140 void OnDefault(void *userData, const XML_Char *s, int len)
00141 {
00142        XML_Char *pString = new XML_Char[len + 1];
00143        memset(pString, 0, sizeof(XML_Char) * (len + 1));
00144        memcpy(pString, s, sizeof(XML_Char) * len);
00145 
00146        USES_CONVERSION;
00147        ATLTRACE(_T("OnDefault: \"%s\"\n"), X2T(pString));
00148 
00149        // TODO test if the buffer contains <?xml version="X"?>
00150        //      and store version in XML document
00151 
00152        // TODO test if the buffer contains DTD and store it
00153        //      in the XML document
00154 
00155        // TODO test if the buffer contains a comment, i.e. <!--.*-->
00156        //      and create a comment XML element
00157 
00158        delete []pString;
00159 }
00160 
00161 
00162 void OnCharacterData(void *userData, const XML_Char *s, int len)
00163 {
00164        ParserState *pState = (ParserState *) userData;
00165        if (pState)
00166        {
00167               // TODO create TEXT element
00168        }
00169 }
00170 
00171