MSXML。以Base64格式获取数据

时间:2010-12-11 21:19:40

标签: c++ xml base64 msxml

我正在使用C ++和MSXML,并希望从XML文件中获取数据作为Base64。我正在使用此代码:

    hr = nodeList->get_item((long)i, (IXMLDOMNode **)&vXMLNode);
    if ( FAILED(hr) )
        throw "Unable to retrieve child node";

    vXMLNode->put_dataType(_bstr_t("bin.base64"));

    hr = vXMLNode->get_nodeTypedValue(&varValue);
    if ( FAILED(hr) )
        throw "Unable to retrieve 'xmltext' text";

所以vXMLNode是一个包含数据的子节点。 vXMLNode的节点类型为NODE_ELEMENT。如果我检查此节点的数据类型,我会得到VT_NULL。因此,我将数据作为字符串。

我的代码有什么问题?

1 个答案:

答案 0 :(得分:1)

我认为问题出在您提供的示例代码之外。这是一个使用nodeTypedValue的工作控制台程序。我希望这会有所帮助。

// Base64CPP.cpp : Defines the entry point for the console application.

//  NOTE:
//  This code is provided as is in the form of a sample with no warranties of any kind, 
//  either expressed or implied for any purpose. Use at your own risk.

#include "stdafx.h"

#include <TCHAR.H>
#include <stdio.h>
#include <sys/stat.h>
#include <fstream>
#include <string.h>

#include <atlbase.h>
#import <msxml4.dll> named_guids
using namespace MSXML2;

inline void EVAL_HR( HRESULT _hr ) 
   { if FAILED(_hr) throw(_hr); }

//  Binary to Base64 Encoding
bool DoEncoding(LPCTSTR lpszXMLFile, LPCTSTR lpszBinFile)
{
    bool bRetVal = false;
    try
    {
        long lFileSize;
        struct stat fileSizeVal;

        //  Get the file size
        if (stat(lpszBinFile, &fileSizeVal) == 0)
        {
            lFileSize = fileSizeVal.st_size;
            if(lFileSize <= 0)
                return false;
        }
        else 
            return false;

        //  Instantiate XML DOMDocument
        CComPtr<IXMLDOMDocument2> spXMLDoc;
        CComPtr<MSXML2::IXMLDOMElement> spDataElement;
        HRESULT hr = spXMLDoc.CoCreateInstance(CLSID_DOMDocument40);
        EVAL_HR(hr);
        spXMLDoc->loadXML(_T("<?xml version='1.0' encoding='UTF-8'?> <Data/>"));

        //  Prepare the top node to store binary data as base64
        spDataElement = spXMLDoc->documentElement;
        ATLASSERT(spDataElement != NULL && _T("Failed to get document element."));

        hr = spDataElement->put_dataType(CComBSTR(_T("bin.base64")));
        EVAL_HR(hr);

        //  Read the file into memory
        std::ifstream binDataFile;
        binDataFile.open(lpszBinFile, std::ios::binary);
        binDataFile.seekg(std::ios::beg);
        SAFEARRAY* psa = SafeArrayCreateVector( VT_UI1, 0L, lFileSize);
        binDataFile.read((char*)psa->pvData, lFileSize);
        binDataFile.close();

        //  Save the binary data into Data node
        VARIANT var;
        VariantInit(&var);
        var.parray = psa;
        var.vt = (VT_ARRAY | VT_UI1 );
        spDataElement->nodeTypedValue = var;

        //  Save the XML Document
        spXMLDoc->save(lpszXMLFile);

        bRetVal = true;
    }
    catch(int)
    {
        //TODO: Error handling
        printf(_T("Exception raised!"));
    }

    return bRetVal;
}

//  Base64 to binary decoding
bool DoDecoding(LPCTSTR lpszXMLFile, LPCTSTR lpszBinFile)
{
    bool bRetVal = false;
    try
    {
        //  Instantiate DOMDocument and load XML file
        CComPtr<IXMLDOMDocument2> spXMLDoc;
        CComPtr<MSXML2::IXMLDOMElement> spDataElement;
        HRESULT hr = spXMLDoc.CoCreateInstance(CLSID_DOMDocument40);
        EVAL_HR(hr);
        CComVariant vtFileName = CComBSTR(lpszXMLFile);
        spXMLDoc->load(vtFileName);

        //  ASSUMPTION: documentElement (top element) contains base64 data
        spDataElement = spXMLDoc->documentElement;
        ATLASSERT(spDataElement != NULL && _T("Failed to get document element."));

        //  Prepare the file for writing
        std::ofstream binDataFile (lpszBinFile, std::ios::out | std::ios::binary);

        //  Save the binary data into data file
        long lDataLength=0;
        hr = SafeArrayGetUBound(spDataElement->nodeTypedValue.parray, 1, &lDataLength);
        EVAL_HR(hr);
        lDataLength++;

        binDataFile.write((char*)(spDataElement->nodeTypedValue.parray->pvData), lDataLength);
        binDataFile.close();

        bRetVal = true;
    }
    catch(int)
    {
        //TODO: Error handling
        printf(_T("Exception raised!"));
    }

    return bRetVal;
}

int main(int argc, char* argv[])
{
    if(argc < 4)
    {//insufficient parameters
        printf(_T("\nSample app to encode/decode binary data as base64 XML using MSXML.\n"));
        printf(_T("\nUsage:\tBase64CPP.exe <e>|<d> <XMLFileName> <BinaryDataFile>"));
        printf(_T("\n\nExamples:"));
        printf(_T("\n\tEncode binary data in 1.jpg and save as Base64 into 1.xml:"));
        printf(_T("\n\t\tBase64CPP.exe e c:\\1.xml c:\\1.jpg\n"));
        printf(_T("\n\tDecode base64 data in 1.xml and save as binary into 2.jpg:"));
        printf(_T("\n\t\tBase64CPP.exe d c:\\1.xml c:\\2.jpg\n\n"));
        return -1;
    }

    try
    {
        HRESULT hr = CoInitialize(NULL);
        EVAL_HR(hr);

        if(_tcsicmp(argv[1], _T("e")) == 0)
        {
            if(DoEncoding(argv[2], argv[3]))
                printf(_T("Success. See %s for results."), argv[2]);
            else
                printf(_T("Failed."));
        }
        else
        {
            if(DoDecoding(argv[2], argv[3]))
                printf(_T("Success. See %s for results."), argv[3]);
            else
                printf(_T("Failed."));
        }
    }
    catch(int)
    {
        //TODO: Error handling
        printf(_T("Exception raised!"));
    }

    CoUninitialize();
    getchar();
    return 0;
}