文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>C/C++程序里处理XML文件

C/C++程序里处理XML文件

时间:2010-12-24  来源:teiller2008

    选择二:MS的MSXML,我要介绍的就是这个。

    先说一下在MSDN哪里找文档吧,往下看的时候也好有个参考:在Index里打:Windows Media Services 9 Series SDK=>Programming Reference=>Programming Reference (C++)=>XML DOM Interfaces (C++)。什么?Windows Media?呵呵,不错,我觉得这个guide反而是最清楚的,你直接找MSXML,得到的结果,我觉得还没这个好。

    在C程序里调用MSXML基本就是一堆COM接口,不过在Visual Studio里操作先要做点简单的设置:

    在你的Project里Add References=>COM标签=>Microsoft XML v4.0,5.0其实也有了,但因为是和Office一起发布的,觉得有点怪,不想用,反正也未必用什么很怪异的功能,4.0可以了。

 

    然后在加入这两行:

    #include <msXML2.h>
    #import <msXML4.dll>

    头文件和dll库。什么?在哪里加?头文件或者c/cpp文件啊,哪里合适放哪儿。

    然后就开始编程了,先定义两个必用的变量:

    IXMLDOMDocumentPtr XMLFile = NULL;
    IXMLDOMElement* XMLRoot = NULL;

    为什么是必用的?  汗...

    第一步当然是初始化COM:

    if(FAILED(CoInitialize(NULL))) ....

    接下来初始化XMLFile对象:

    if(FAILED(XMLFile.CreateInstance("MsXML2.DOMDocument.4.0"))) ...

    然后就可以加载XML文件了:

    _variant_t varXML(L"C:\\test.XML"); //L for unicode
    VARIANT_BOOL varOut;
    XMLFile->load(varXML, &varOut);

    取得root element:

    XMLFile->get_documentElement(&XMLRoot))

    取得第一级element:

    IXMLDOMNodeList* XMLChildNodes = NULL;
    XMLRoot->get_childNodes(&XMLChildNodes);

    遍历所有第一级element:

    IXMLDOMNode* currentNode = NULL;
    while(!FAILED(XMLChildNodes->nextNode(&currentNode)) && currentNode != NULL)

 

    {
    //do something
    }

    取得当前element的名称:

    BSTR nodeName;
    currentNode->get_nodeName(&nodeName);

    取得当前element的一个attribute(假设这个attribute叫type)的值:

    IXMLDOMNamedNodeMap* attributes = NULL;
    IXMLDOMNode* attributeName = NULL;
    _bstr_t bstrAttributeName = "type";
    BSTR nameVal;
    currentNode->get_attributes(&attributes);
    attributes->getNamedItem(bstrAttributeName, &attributeName);
    attributeName->get_text(&nameVal);

    需要注意的是,你要记住释放所有的借口,IXMLDOM***->Release(),这可不是.NET,有人帮你GC,你得自己调用Release()来减reference count,it's COM, remember?

    好了,大致就这样,顺便提一下XPath:

    _bstr_t bstrXMLQuery = L"/books/book[@type=scifi and @author=fox]";
    IXMLDOMNodeList* nodes = NULL;
    if(FAILED(XMLRoot->selectNodes(bstrXMLQuery, &nodes)) FAILED(nodes->get_length(&length)) length == 0)
    //no match found or something went wrong
    else
    //match found

    上面是找这样的node:

    <books>
    <book type="scifi" author="fox">....
    </book>
    ....
    </books>

    具体的XPath语法就查手册吧,到处都有。

    哦,对了,忘了说:如果你全部用ATL的类的话,借口的调用会简单一点,不过很容易转换的,比如:

    IXMLDOMDocument* 对应 IXMLDOMDocumentPtr(我这里用了),其他基本也是加个Ptr,我不废话了。

    最后提供一个sample,我临时攒的。工作的时候写的程序当然不能拿来贴的,呵呵。这个sample基本就是遍历整个XML,然后报告一遍文件的结构,对每个node,如果它有一个叫id的attribute,就同时打印id的值。If you want the complete VS project, shoot me an email. But I guess no one really needs it anyway, right, : )

    #include "stdafx.h"
    #include <windows.h>
    #include <msXML2.h>
    #import <msXML4.dll>

    HANDLE logFile = NULL;

    #define INDENT 4

#define TESTHR(hr)
    {
    if(FAILED(hr)) goto fail;
    }

    void PrintChild(IXMLDOMNodeList* nodeList, int level)
    {
    if(nodeList == NULL)
    return;

    IXMLDOMNode* currentNode = NULL;
    IXMLDOMNodeList* childNodes = NULL;
    IXMLDOMNamedNodeMap* attributes = NULL;
    IXMLDOMNode* attributeID = NULL;

    while(!FAILED(nodeList->nextNode(&currentNode)) && currentNode != NULL)
    {
    BSTR nodeName;
    TESTHR(currentNode->get_nodeName(&nodeName));
    DWord dwBytesWritten;
    for(int i=0; i<level*INDENT; i++)
    WriteFile(logFile, L" ", (Dword)(sizeof(WCHAR)), &dwBytesWritten, NULL);

    //WCHAR msg[MAX_SIZE];
    //wsprintf(msg, L"%s ", nodeName);
    WriteFile(logFile, nodeName, (Dword)(wcslen(nodeName)*sizeof(WCHAR)), &dwBytesWritten, NULL);

    TESTHR(currentNode->get_attributes(&attributes));
    if(attributes!=NULL)
    {
    _bstr_t bstrAttributeName = "id";
    BSTR idVal;
    TESTHR(attributes->getNamedItem(bstrAttributeName, &attributeID));
    if(attributeID != NULL)
    {
    TESTHR(attributeID->get_text(&idVal));
    WriteFile(logFile, L" ", (Dword)(sizeof(WCHAR)), &dwBytesWritten, NULL);
    WriteFile(logFile, idVal, (Dword)(wcslen(idVal)*sizeof(WCHAR)), &dwBytesWritten, NULL);
    WriteFile(logFile, L"\r\n", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL);
    attributeID->Release(); attributeID = NULL;
    }
    else
    {
    WriteFile(logFile, L"\r\n", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL);
    }
    attributes->Release(); attributes = NULL;

    }
    else
    {
    WriteFile(logFile, L"\r\n", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL);
    }

    TESTHR(currentNode->get_childNodes(&childNodes));
    PrintChild(childNodes, level+1);
    currentNode=NULL;
    }

    fail:
    if(childNodes!=NULL)
    childNodes->Release();
    if(attributeID!=NULL)
    attributeID->Release();
    if(attributes!=NULL)
    attributes->Release();
    if(currentNode != NULL)
    currentNode->Release();
    }

    int _tmain(int argc, _TCHAR* argv[])
    {

    IXMLDOMDocumentPtr XMLFile = NULL;
    IXMLDOMElement* XMLRoot = NULL;
    _variant_t varXML(L"C:\\demo1.XML");

    logFile = CreateFile(L"log.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if(logFile == INVALID_HANDLE_VALUE)
    goto fail;

    TESTHR(CoInitialize(NULL));

    TESTHR(XMLFile.CreateInstance("MsXML2.DOMDocument.4.0"));

    VARIANT_BOOL varOut;
    TESTHR(XMLFile->load(varXML, &varOut));

    TESTHR(XMLFile->get_documentElement(&XMLRoot));

    BSTR rootName;
    Dword dwBytesWritten;
    TESTHR(XMLRoot->get_nodeName(&rootName));
    WriteFile(logFile, rootName, (Dword)(wcslen(rootName)*sizeof(WCHAR)), &dwBytesWritten, NULL);
    WriteFile(logFile, L"\r\n", (Dword)(2*sizeof(WCHAR)), &dwBytesWritten, NULL);

    IXMLDOMNodeList* XMLChildNodes = NULL;
    TESTHR(XMLRoot->get_childNodes(&XMLChildNodes));

    PrintChild(XMLChildNodes, 2);
    fail:
    if(logFile != INVALID_HANDLE_VALUE)
    CloseHandle(logFile);
    if(XMLChildNodes!=NULL)
    XMLChildNodes->Release();

相关阅读 更多 +
排行榜 更多 +
翌日波奇狗的历险记手机版下载

翌日波奇狗的历险记手机版下载

休闲益智 下载
怪兽远征安卓版下载

怪兽远征安卓版下载

角色扮演 下载
谷歌卫星地图免费版下载

谷歌卫星地图免费版下载

生活实用 下载