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

📄 xmldatarecordparser.cpp

📁 一个WinCE6。0下的IP phone的源代码
💻 CPP
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "xmldatarecordparser.h"
#include <atlbase.h>

#define INVALID_ITEM      -1

#ifdef DEBUG
VOID DumpDataRecordList(RefCountedDataRecordList *m_pDataRecordList)
{
    for (INT i = 0; i < m_pDataRecordList->size(); ++i)
    {
        for (INT j = 0; j < m_pDataRecordList->DataRecordSize(); ++j)
        {
            DataRecord *p = (*m_pDataRecordList)[i];
            DataRecord::string &str = (*p)[j];
            
            DEBUGMSG(ZONE_OWAEC_PARSE_RESULTS, (L"Item %d, property %d value %s", i, j, (const WCHAR*)(str.get_buffer())));
        }
    }
}
#endif

/*------------------------------------------------------------------------------
    ToSAXHR
    
    According to the SAX documentation, all API's that implement ISAXContentHandler
    must return either S_OK or E_FAIL. Thus all of the implementations we provide for
    ContentHandler must be wrapped with these values.
    
    Parameters:
        hr: The HRESULT to cast to a SAX Hresult
    
    Returns (HRESULT): S_OK on success or E_FAIL on failure
------------------------------------------------------------------------------*/
inline HRESULT ToSAXHR(HRESULT hr)
{
    return (SUCCEEDED(hr)) ? S_OK : E_FAIL;
}

/*-----------------------------------------

    Constructor/Destructor Implementation
    
------------------------------------------*/
CXMLDataRecordParser::CXMLDataRecordParser()
{
    TRACE_(ZONE_OWAEC_TRACING_CTOR);
    MemTrackAdd();

    m_cRefs                 = 1;
    m_idxCurrentParsingItem = INVALID_ITEM;
    m_pCurrentDataRecord        = NULL;
    m_pDataRecordList           = NULL;

    m_piXMLReader           = NULL;
};

CXMLDataRecordParser::~CXMLDataRecordParser()
{
    TRACE_(ZONE_OWAEC_TRACING_CTOR);
    MemTrackRemove();

    ASSERT(m_pCurrentDataRecord == NULL);
    
    if (m_piXMLReader)
    {
        m_piXMLReader->Release();
        m_piXMLReader = NULL;
    }
}

/*----------------------------------------

    Public Function Implementation
    
------------------------------------------*/

/*------------------------------------------------------------------------------
    CXMLDataRecordParser::SetDataRecordPropertyKeyword
    
    Set a property mapping
    
    Parameters:
        idxProperty:  The index of the property to be mapped
        c_wszProperty: The property name tag
------------------------------------------------------------------------------*/
HRESULT CXMLDataRecordParser::SetDataRecordPropertyKeyword(INT idxProperty, const WCHAR * c_wszProperty)
{
    if (idxProperty < 0 || idxProperty >= MAX_DATARECORD_PROPERTIES)
    {
        return E_INVALIDARG;
    }

    if (c_wszProperty == NULL)
    {
        return E_POINTER;
    }

    //ce::wstring assignment does a str copy
    if (!m_wstrPropertyMapping[idxProperty].assign(c_wszProperty))
    {
        return E_OUTOFMEMORY;
    }
    
    return S_OK;
}

/*------------------------------------------------------------------------------
    CXMLDataRecordParser::SetNewDataRecordKeyword
    
    Sets the tag which will prompt the creation of a new datarecord during parsing
------------------------------------------------------------------------------*/
HRESULT CXMLDataRecordParser::SetNewDataRecordKeyword(const WCHAR * c_wszNewDataRecord)
{
    if (c_wszNewDataRecord == NULL)
    {
        return E_POINTER;
    }

    //ce::wstr assign does a copy
    if (!m_wstrNewDataRecordName.assign(c_wszNewDataRecord))
    {
        return E_OUTOFMEMORY;
    }
    return S_OK;
}

/*------------------------------------------------------------------------------
    CXMLDataRecordParser::Parse
    
    Parse an XML string according to the property mapping and push the results into 
    the given datarecordlist
    
    Parameters:
        bstrXML:     The xml to parse
        pDataRecordList: The datarecord list which will store the results
------------------------------------------------------------------------------*/
HRESULT CXMLDataRecordParser::Parse(BSTR bstrXML, RefCountedDataRecordList * pDataRecordList)
{
    if (bstrXML == NULL || pDataRecordList == NULL)
    {
        return E_POINTER;
    }

    m_pDataRecordList = pDataRecordList;
    //Stabalize the list
    m_pDataRecordList->AddRef();

    HRESULT                     hr               = S_OK;
    CComPtr<ISAXContentHandler> cpContentHandler;

    //Create the SAXXmlReader
    if (m_piXMLReader == NULL)
    {
        hr = CoCreateInstance(
            CLSID_SAXXMLReader,
            NULL,
            CLSCTX_INPROC_SERVER,
            IID_ISAXXMLReader,
            reinterpret_cast<void **>(&m_piXMLReader)
            );
    }

    //Get the content handler interface to give to the XMLReader
    if (SUCCEEDED(hr))
    {
        hr = QueryInterface(
            IID_ISAXContentHandler, 
            reinterpret_cast<void **>(&cpContentHandler)
            );
    }

    //register the content handler with the xml reader
    if (SUCCEEDED(hr))
    {
        ASSERT(m_piXMLReader);
        hr = m_piXMLReader->putContentHandler(cpContentHandler);
    }

    //parse the xml
    if (SUCCEEDED(hr))
    {
        VARIANT varParse = {0};
        varParse.vt      = VT_BSTR;
        varParse.bstrVal = bstrXML;
           
        hr = m_piXMLReader->parse(varParse);
    }

#ifdef DEBUG
    //debugout the datarecord list
    DumpDataRecordList(m_pDataRecordList);
#endif

    //cleanup
    m_idxCurrentParsingItem = INVALID_ITEM;
    m_pDataRecordList->Release();
    m_pDataRecordList = NULL;

    return hr;
}

HRESULT CXMLDataRecordParser::ClearMapping()
{
    m_wstrNewDataRecordName.clear();

    for (INT i = 0; i < MAX_DATARECORD_PROPERTIES; i++)
    {
        m_wstrPropertyMapping[i].clear();
    }
    return S_OK;
}
/*-----------------------------------------

    IUnknown Implementation
    
------------------------------------------*/
ULONG STDMETHODCALLTYPE CXMLDataRecordParser::AddRef()
{
    return ++m_cRefs;
}

ULONG STDMETHODCALLTYPE CXMLDataRecordParser::Release()
{
    INT cRefs = --m_cRefs;
    if (cRefs <= 0)
        delete this;
    
    return cRefs;
}

STDMETHODIMP CXMLDataRecordParser::QueryInterface(REFIID refiid, VOID **ppvObject)
{
    HRESULT hr = S_OK;

    if (ppvObject == NULL)
    {
        return E_POINTER;
    }

    if (refiid == IID_IUnknown)
    {
        (*ppvObject) = static_cast<IUnknown*>(this);
        AddRef();
    }
    else if (refiid == IID_ISAXContentHandler)
    {
        (*ppvObject) = static_cast<ISAXContentHandler*>(this);
        AddRef();
    }

    else
    {
        hr = E_NOINTERFACE;
    }

    return hr;
}

/*-----------------------------------------

    ISAXContentHandler Implementation
    
------------------------------------------*/


/*------------------------------------------------------------------------------
    CXMLDataRecordParser::characters
    
    If we are currently inside a recognized tag, then 
    collect the rest of the text and store it in the current datarecord
------------------------------------------------------------------------------*/
STDMETHODIMP CXMLDataRecordParser::characters(
    const WCHAR *pwchChars         ,
    INT          cchChars
    )
{
    //check to see if we are in a collection state
    if (m_idxCurrentParsingItem == INVALID_ITEM)
    {
        return S_OK;
    }

    //if we are, collect all the char's up the the next open angle bracket
    return ToSAXHR(AddPropertyToCurrentDataRecord(
        pwchChars, 
        cchChars
        ));
}

/*------------------------------------------------------------------------------
    CXMLDataRecordParser::startElement
    
    Check the current tag to see if its one we recognize. If it is one we are searching
    for, do the appropriate action (e.g. on new-datarecord-tag create a new-datarecord etc).
------------------------------------------------------------------------------*/
STDMETHODIMP CXMLDataRecordParser::startElement(
    const WCHAR *pwchNamespaceUri  , 
    INT          cchNamespaceUri   , 
    const WCHAR *pwchLocalName     , 
    INT          cchLocalName      ,
    const WCHAR *pwchQName         ,
    INT          cchQName          ,
    ISAXAttributes* pAttributes
    )
{
    //paranoid: check parameters
    if (pwchLocalName == NULL)
    {
        return S_OK;
    }

    HRESULT hr         = S_OK;

    //check the new datarecord tag with the local name tag
    if (wcsnicmp(m_wstrNewDataRecordName, pwchLocalName, min(wcslen(m_wstrNewDataRecordName), cchLocalName)) == 0)
    {
        hr = CreateNewDataRecord();
    }
    else
    {
        BOOL fMatch = FALSE;

        //Run through the property mapping to see if this tag matches a property we want
        for (INT i = 0; i < MAX_DATARECORD_PROPERTIES; i++)
        {
            if (
                m_wstrPropertyMapping[i][0] != 0 &&
                (wcsnicmp(m_wstrPropertyMapping[i], pwchLocalName, min(wcslen(m_wstrPropertyMapping[i]), cchLocalName)) == 0)
                )
            {
                m_idxCurrentParsingItem = i;
                fMatch = TRUE;
                break;
            }
        }

        if (!fMatch)
        {
            m_idxCurrentParsingItem = INVALID_ITEM;
        }
    }
    
    return ToSAXHR(hr);
}

/*------------------------------------------------------------------------------
    CXMLDataRecordParser::endElement
    
    If this tag is the end of the new datarecord tag, commit the current open datarecord
    to the datarecord list
------------------------------------------------------------------------------*/
STDMETHODIMP CXMLDataRecordParser::endElement(
    const WCHAR *pwchNamespaceURI  ,
    INT          cchNamespaceURI   ,
    const WCHAR *pwchLocalName     ,
    INT          cchLocalName      ,
    const WCHAR *pwchQName         ,
    INT          cchQName
    )
{
    HRESULT hr = S_OK;
    if (wcsnicmp(m_wstrNewDataRecordName, pwchLocalName, min(wcslen(m_wstrNewDataRecordName), cchLocalName)) == 0)
    {
        hr = CommitCurrentDataRecord();
    }
    
    m_idxCurrentParsingItem = INVALID_ITEM;

    return ToSAXHR(hr);
}

/*-----------------------------------------

    Private Functions Implementation
    
------------------------------------------*/

/*------------------------------------------------------------------------------
    CXMLDataRecordParser::CreateNewDataRecord
    
    Create a new datarecord to later be pushed into the datarecord list
------------------------------------------------------------------------------*/
HRESULT     CXMLDataRecordParser::CreateNewDataRecord()
{
    //Check that we are not adding a new datarecord when there is still an open datarecord
    ASSERT(m_pCurrentDataRecord == NULL);
    m_idxCurrentParsingItem = INVALID_ITEM;
    return m_pDataRecordList->CreateNewDataRecord(&m_pCurrentDataRecord);
}

/*------------------------------------------------------------------------------
    CXMLDataRecordParser::CommitCurrentDataRecord
    
    Push the current datarecord into the DataRecordList
------------------------------------------------------------------------------*/
HRESULT     CXMLDataRecordParser::CommitCurrentDataRecord()
{
    if (m_pCurrentDataRecord == NULL)
    {
        ASSERT(FALSE);
        return E_UNEXPECTED;
    }

    if (! m_pDataRecordList->push_back(m_pCurrentDataRecord) )
    {
        return E_OUTOFMEMORY;
    }
    
    m_pCurrentDataRecord    = NULL;
    m_idxCurrentParsingItem = INVALID_ITEM;
    return S_OK;
}

/*------------------------------------------------------------------------------
    CXMLDataRecordParser::AddPropertyToCurrentDataRecord
    
    Add a property string to the current open datarecord
------------------------------------------------------------------------------*/
HRESULT     CXMLDataRecordParser::AddPropertyToCurrentDataRecord(const WCHAR *pwchProperty, INT cchProperty)
{
    if (pwchProperty == NULL)
    {
        return E_POINTER;
    }

    //check that we are in a state that can add a property
    if (
        m_pCurrentDataRecord == NULL || 
        m_idxCurrentParsingItem < 0
        )
    {
        ASSERT(FALSE);
        return E_INVALIDARG;
    }

    if (!(*m_pCurrentDataRecord)[m_idxCurrentParsingItem].append(pwchProperty, cchProperty))
    {
        return E_OUTOFMEMORY;
    }

    return S_OK;
}


⌨️ 快捷键说明

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