史上最も信頼性が高く、MSXMLベースのXML解析ガイド-C++
史上最も信頼性が高く、MSXMLベースのXML解析ガイド-C++
最近はC++関連のプロジェクトをしていて、COMとMSXMLを併用してXMLファイルの情報を解析する問題に遭遇していますが、このような問題はMFC開発でもよく使われています.ネットで丸ごと検索してみると、確かに利用可能なcodeを見つけるのは難しいので、やっと自分で効率的で簡単な方法を研究して、この機会にまとめて、みんなに共有します.
付VS Projectミラー:SimpleParser 4 MSXML-cpp:C++言語で書かれたMSXMLの簡単な使用例、COMとMFC開発でよく使われています.https://github.com/yanglr/Sim...「Raw」をクリックするとソースが表示されます.forkまたはstarを歓迎します.
まずMSXML技術の基本的な特徴を簡単に列挙する.
COMの技術に基づいて、Windowsオペレーティングシステムに付属するXMLを処理する.
MSXML
DOM本体実装を提供し、XPathとXSLTをサポートします.
SAX 2ベースのイベントを含むアナライザ.
プロセス設計
まず、大まかな流れを簡単に紹介します.初期化COM IDOMDocumentオブジェクトxmlDocを作成し、xmlDoc->load()またはloadXML()メソッドを使用してXMLソース を読み込む selectNodes()またはselectSingleNode()関数を呼び出し、指定したノードオブジェクトを選択します. ノードオブジェクトの内容は、IXMLDOMNodeオブジェクトの属性および方法によって読み取られる. ノードオブジェクトの内容は、IXMLDOMNodeオブジェクトの属性およびメソッドによって設定される. xmlDoc->save()を呼び出してXMLファイルを保存します. COM を閉じる
解決すべき問題: xml情報のいくつかの読み取り形式(xmlファイルまたはwchar) ノードをどのように選択し、andノード属性を取得するにはどのような方法がありますか? IXMLDOMNodeとIXMLDOMElementインタフェースの関連と違いは何ですか? ノードが配列であれば、どのように操作しますか? プロパティにプロパティを挿入する方法 文字列の変換 xml情報にはどのような読み取り形式がありますか(xmlファイルまたはwchar) xmlファイル ファイルからxmlコンテンツをインポートしurlまたはfilePathを使用
変数方式で人filePathを渡す場合は、c_を使用する必要があります.str()関数を変換します.コードは次のとおりです.文字列形式で読み込まれたxmlフルコード まずBSTR定数を定義します
次に、BSTRからxmlコンテンツをインポートします.
注意:BSTR文字列はCOMコンポーネントオブジェクトモデルの文字列形式で、文字列の長さを表す4バイトの整数で始まり、UTF-16符号化wchar_に続くt文字列(0終了フラグを含む).BSTRタイプの変数は、文字列の最初の文字を指すポインタです.
どのようにノードを選択して、andノードの属性を取るにはどのような方法がありますか?検索ノード名
IXMLDOMNodeとIXMLDOMElementインタフェースの関連性と違い
IXMLDOMElementインタフェースはIXMLDOMNodeインタフェースに継承されますが、IXMLDOMNodeインタフェースから継承する方法に加えて、IXMLDOMElementインタフェースは次の方法にも露出します.
方法
説明
get_tagName
要素名(tag間のテキスト)を取得します.
getAttribute
指定した名前の属性の値を取得します.
getAttributeNode
指定した名前の属性を取得するノード
getElementsByTagName
指定した名前に一致するすべてのサブ要素のリストを取得します.
removeAttribute
指定した名前の属性の移動または置換
removeAttributeNode
この要素から指定した属性を除去
setAttribute
指定した名前の属性に値を設定
setAttributeNode
指定した属性ノードをこの要素に追加または置換します.
ノードが配列の場合、どのように操作しますか?
get_を先に使用childNodes関数はサブノードのリストを取得し、get_を使用して巡回します.itemは各項目を順次取り出して処理する.
属性の挿入方法
Element->setAttribute()を使用すると、次のようになります.
文字列の変換と出力はprintf関数+"%ls"またはwprintf関数+"%s"を直接使用してBSTRクラス文字列 を印刷する.
または CComBSTRクラス文字列の内容をwstringにコピーし、wcout出力 を使用する. CComBSTRクラス文字列をLPCTSTRタイプに強く変換した後、wcout出力 を使用する.
CStringWクラスの文字列では、これは比較的簡単な方法です. CComBSTRクラス文字列の内容をCW 2 Aクラス文字列(マルチバイト文字列)にコピーし、wcout出力 を使用する.
プライマリコード
実行結果:
実行が完了し、取得したupdate.xmlの内容は次のとおりです.https://raw.githubusercontent...参考資料: IXMLDOMElementインタフェース Using the MSXML Parser MFC C++ XML Parse - Using MSXML は、さまざまな文字列タイプ間の変換|Microsoft Docs 本文は本人csdnブログに掲載されています→https://blog.csdn.net/lzuacm/...
最近はC++関連のプロジェクトをしていて、COMとMSXMLを併用してXMLファイルの情報を解析する問題に遭遇していますが、このような問題はMFC開発でもよく使われています.ネットで丸ごと検索してみると、確かに利用可能なcodeを見つけるのは難しいので、やっと自分で効率的で簡単な方法を研究して、この機会にまとめて、みんなに共有します.
付VS Projectミラー:SimpleParser 4 MSXML-cpp:C++言語で書かれたMSXMLの簡単な使用例、COMとMFC開発でよく使われています.https://github.com/yanglr/Sim...「Raw」をクリックするとソースが表示されます.forkまたはstarを歓迎します.
まずMSXML技術の基本的な特徴を簡単に列挙する.
COMの技術に基づいて、Windowsオペレーティングシステムに付属するXMLを処理する.
MSXML
DOM本体実装を提供し、XPathとXSLTをサポートします.
SAX 2ベースのイベントを含むアナライザ.
プロセス設計
まず、大まかな流れを簡単に紹介します.
解決すべき問題:
VARIANT_BOOL bSuccess = false;
HRESULT hr = iXMLDoc->load(CComVariant(L"./test.xml"), &bSuccess); // L
変数方式で人filePathを渡す場合は、c_を使用する必要があります.str()関数を変換します.コードは次のとおりです.
VARIANT_BOOL bSuccess = false;
filePath = "./test.xml";
HRESULT hr = iXMLDoc->load(CComVariant(filePath.c_str()), &bSuccess);
const wchar_t *src = L""
L"\r
"
L"\r
"
L" Hey \r
"
L" \r
"
L" \r
"
L" \r
"
L" \r
"
L" \r
"
L" \r
";
次に、BSTRからxmlコンテンツをインポートします.
VARIANT_BOOL bSuccess = false;
iXMLDoc->loadXML(CComBSTR(src), &bSuccess);
注意:BSTR文字列はCOMコンポーネントオブジェクトモデルの文字列形式で、文字列の長さを表す4バイトの整数で始まり、UTF-16符号化wchar_に続くt文字列(0終了フラグを含む).BSTRタイプの変数は、文字列の最初の文字を指すポインタです.
どのようにノードを選択して、andノードの属性を取るにはどのような方法がありますか?
CComBSTR sstrRoot(L"root"); // sstrRoot("root");
CComPtr rootNode;
HRESULT hr = iXMLDoc->selectSingleNode(sstrRoot, &rootNode);
CComPtr textNode;
hr = rootNode->selectSingleNode(CComBSTR(L"text"), &textNode); // "text"
IXMLDOMNodeとIXMLDOMElementインタフェースの関連性と違い
IXMLDOMElementインタフェースはIXMLDOMNodeインタフェースに継承されますが、IXMLDOMNodeインタフェースから継承する方法に加えて、IXMLDOMElementインタフェースは次の方法にも露出します.
方法
説明
get_tagName
要素名(tag間のテキスト)を取得します.
getAttribute
指定した名前の属性の値を取得します.
getAttributeNode
指定した名前の属性を取得するノード
getElementsByTagName
指定した名前に一致するすべてのサブ要素のリストを取得します.
removeAttribute
指定した名前の属性の移動または置換
removeAttributeNode
この要素から指定した属性を除去
setAttribute
指定した名前の属性に値を設定
setAttributeNode
指定した属性ノードをこの要素に追加または置換します.
ノードが配列の場合、どのように操作しますか?
get_を先に使用childNodes関数はサブノードのリストを取得し、get_を使用して巡回します.itemは各項目を順次取り出して処理する.
CComPtr pRootElement;
CComPtr pNodeList;
pRootElement->get_childNodes(&pNodeList); // Child node list
long nLen;
pNodeList->get_length(&nLen); // Child node list
for (long index = 0; i != nLen; ++index) // Traverse
{
CComPtr pCurNode;
hr = pNodeList->get_item(index, &pCurNode);
do(); //
}
属性の挿入方法
Element->setAttribute()を使用すると、次のようになります.
CComPtr imageElement;
xmlDocData->createElement(CComBSTR(L"Image"), &imageElement); // "Image"
imageElement->setAttribute(CComBSTR(L"Type"), CComVariant(CComBSTR(imageType.c_str()))); // "Type"
文字列の変換と出力
CComBSTR ssName;
printf("Node name:%ls
", ssName); // %ls BSTR
SysFreeString(ssName); //
または
CComBSTR ssName;
wprintf(L"Node name:%s
", ssName); // L
SysFreeString(ssName);
CComBSTR ssName;
wstring bstrText(ssName);
wcout << bstrText << endl;
CStringWクラスの文字列では、これは比較的簡単な方法です.
CComBSTR ssName;
CString cstring(ssName);
wcout << (LPCTSTR)cstring << endl;
CComBSTR ssName;
CW2A printstr(ssName);
cout << printstr << endl;
プライマリコード
#include // MSXML
#include
#include "atlstr.h" // CString, CStringW CW2A
#include // wcout
#include // c_str() , wcout
#include "comutil.h" // _bstr_t
using namespace std;
const wchar_t *src = L""
L"\r
"
L"\r
"
L" Hey \r
"
L" \r
"
L" \r
"
L" \r
"
L" \r
"
L" \r
"
L" \r
";
int main()
{
CoInitialize(NULL); // Initialize COM
CComPtr iXMLDoc; // Or use CComPtr, CComPtr
try
{
HRESULT hr = iXMLDoc.CoCreateInstance(__uuidof(DOMDocument));
// iXMLDoc.CoCreateInstance(__uuidof(DOMDocument60));
// Load the file.
VARIANT_BOOL bSuccess = false;
// Load it from a url/filename...
hr = iXMLDoc->load(CComVariant(L"./test.xml"), &bSuccess);
// filePath = "./test.xml";
// hr = iXMLDoc->load(CComVariant(filePath.c_str()), &bSuccess);
// or from a BSTR...
// iXMLDoc->loadXML(CComBSTR(src), &bSuccess);
// Get a smart pointer (sp) to the root
CComPtr pRootElement;
hr = iXMLDoc->get_documentElement(&pRootElement); // Root elements
// Get Attribute value of the note "root"
CComBSTR ssDesc("desc");
CComVariant deVal(VT_EMPTY);
hr = pRootElement->getAttribute(ssDesc, &deVal);
CComBSTR sstrRoot(L"root"); // sstrRoot("root");
CComPtr rootNode;
hr = iXMLDoc->selectSingleNode(sstrRoot, &rootNode); // Search "root"
CComBSTR rootText;
hr = rootNode->get_text(&rootText);
if (SUCCEEDED(hr))
{
wstring bstrText(rootText);
wcout << "Text of root: " << bstrText << endl;
}
CComPtr descAttribute;
hr = rootNode->selectSingleNode(CComBSTR("@desc"), &descAttribute); // Atrribute @, @
CComBSTR descVal;
hr = descAttribute->get_text(&descVal);
if (SUCCEEDED(hr))
{
wstring bstrText(descVal);
wcout << "Desc Attribute: " << bstrText << endl;
}
if (!FAILED(hr))
{
wstring strVal;
if (deVal.vt == VT_BSTR)
strVal = deVal.bstrVal;
wcout << "desc: " << strVal << endl;
}
CComPtr pNodeList;
pRootElement->get_childNodes(&pNodeList); // Child node list
long nLen;
pNodeList->get_length(&nLen); // Child node list
for (long i = 0; i != nLen; ++i) // Traverse
{
CComPtr pNode;
hr = pNodeList->get_item(i, &pNode);
CComBSTR ssName;
CComVariant val(VT_EMPTY);
hr = pNode->get_nodeName(&ssName);
if (SUCCEEDED(hr))
{
wstring bstrText(ssName);
wcout << "Name of node " << (i + 1) << ": " << bstrText << endl;
CString cstring(ssName);
// To display a CStringW correctly, use wcout and cast cstring to (LPCTSTR), an easier way to display wide character strings.
wcout << (LPCTSTR)cstring << endl;
// CW2A converts the string in ccombstr to a multi-byte string in printstr, used for display output.
CW2A printstr(ssName);
cout << printstr << endl;
}
}
/// Add(Append) node
CComPtr& xmlDocData(iXMLDoc);
CComPtr imageElement;
CComPtr newImageNode;
string imageType = "jpeg";
char buffer[MAX_PATH];
GetCurrentDirectory(MAX_PATH, buffer); // Get Current Directory
string path(buffer); // Copy content of char*, generate a string
string imagePath = path + "\\com.jpg";
xmlDocData->createElement(CComBSTR(L"Image"), &imageElement);
imageElement->setAttribute(CComBSTR(L"Type"), CComVariant(CComBSTR(imageType.c_str()))); //
imageElement->setAttribute(CComBSTR(L"FileName"), CComVariant(CComBSTR(imagePath.c_str())));
rootNode->appendChild(imageElement, &newImageNode);
/// Remove "text" node under "root" node
CComPtr xmlOldNode;
CComPtr textNode;
hr = rootNode->selectSingleNode(CComBSTR(L"text"), &textNode); // Search "text" node
hr = rootNode->removeChild(textNode, &xmlOldNode);
/// Update XML
hr = iXMLDoc->save(CComVariant("updated.xml"));
}
catch (char* pStrErr) {
// Some error...
std::cout << pStrErr << std::endl << std::endl;
} // catch
catch (...) {
// Unknown error...
std::cout << "Unknown error..." << std::endl << std::endl;
}
// Release() - that gets done automatically, also can manually do for each opened node or elements.
// iXMLDoc.Release();
// Stop COM
CoUninitialize();
system("pause");
return 0;
}
実行結果:
実行が完了し、取得したupdate.xmlの内容は次のとおりです.https://raw.githubusercontent...参考資料: