C/C++

Trích xuất dữ liệu từ file XML với thư viện tinyXML2

Xin chào, bài viết này giới thiệu về tinyXML2, một thư viện C++ dùng để xử lý file XML. Trong khuôn khổ bài viết chúng ta sẽ tìm hiểu cách trích xuất dữ liệu từ file XML.


Các functions quan trọng

Đầu tiên chúng ta cần clone thư viện tinyXML2 về từ Github. Vì không phải là standard library của C++ nên documentation của tinyXML2 không tốt lắm, tuy nhiên chỉ cần đọc qua file header kèm với vài examples thì chúng ta đã có thể sử dụng thư viện này để trích xuất dữ liệu rồi!

Trước đây mình cũng đã có một bài viết về thư viện XML của Python, các bạn có thể tham khảo nếu cần.

Namespace: tinyxml2

Các class quan trọng:

+XMLDocument – instance của class này chứa toàn bộ dữ liệu của file XML. Class XMLDocument có 3 methods quan trọng là LoadFile(), RootElement() và ErrorIDToName().

  • XMLError LoadFile(const char* filename) – load file XML có tên filename;
  • XMLError LoadFile(FILE* file) – load file XML từ file object;
  • XMLElement* RootElement() – đọc root element của XML Object, kết quả trả về là một pointer đến một XMLElement instance;
  • static const char* ErrorIDToName(XMLError errorID) – trả về error string tương ứng với errorID.

+ XMLElement – instance của class này chứa dữ liệu của một điểm dữ liệu của XML Object. Class XMLElement có các methods quan trọng sau: FirstChildElement(), LastChildElement(), NextSiblingElement(), PreviousSiblingElement(), QueryAttribute(), QueryStringAttribute() và GetText().

CHÚ Ý: Một điểm dữ liệu (còn gọi là element) trong XML được biểu diễn như sau:

<tagname attribute_1=”value_1” attribute_2=”value_2text/sub-element </tagname>

  • XMLElement* FirstChildElement(const char* tagname) – trả về pointer trỏ đến sub-element đầu tiên của element hiện tại với tagname;
  • XMLElement* LastChildElement(const char* tagname) – trả về pointer trỏ đến sub-element cuối cùng của element hiện tại với tagname;
  • XMLElement* NextSiblingElement() – trả về pointer trỏ đến element kế tiếp của element hiện tại;
  • XMLElement* PreviousSiblingElement() – trả về pointer trỏ đến element trước đó của element hiện tại;
  • XMLError QueryAttribute(const char* attribName, T* value ) – truy cập attribute value của element;
  • XMLError QueryStringAttribute(const char* attribName, const char** value) – truy cập string attribute value của element;
  • const char* GetText() – truy cập text value của element.

Ví dụ

Dữ liệu: data.xml

<?xml version='1.0' encoding='ISO-8859-1'?>
<?xml-stylesheet type='text/xsl' href='image_metadata_stylesheet.xsl'?>
<dataset>
    <name>imglab dataset</name>
    <comment>Created by imglab tool.</comment>
    <images>
        <image file='cardataset/1000.jpg'>
            <box top='111' left='403' width='72' height='60' ignore='1'/>
            <box top='115' left='525' width='77' height='64'/>
            <box top='84' left='648' width='74' height='64'/>
            <box top='33' left='474' width='47' height='44' ignore='1'/>
            <box top='59' left='533' width='61' height='52' ignore='1'/>
            <box top='13' left='645' width='40' height='29' ignore='1'/>
            <box top='5' left='584' width='37' height='27' ignore='1'/>
        </image>
        <image file='cardataset/1050.jpg'>
            <box top='142' left='360' width='82' height='70'/>
            <box top='264' left='495' width='142' height='134'/>
            <box top='86' left='652' width='71' height='60' ignore='1'/>
            <box top='20' left='636' width='44' height='35' ignore='1'/>
            <box top='44' left='555' width='49' height='36' ignore='1'/>
            <box top='17' left='569' width='36' height='27' ignore='1'/>
            <box top='-6' left='542' width='42' height='27' ignore='1'/>
        </image>
    </images>
</dataset>

Source file: parseXML.cpp

#include <iostream>
#include "tinyxml2.h"

using namespace std;
using namespace tinyxml2;

int main() {

	XMLDocument xmlDoc;
	XMLError eResult = xmlDoc.LoadFile("data.xml");

	if (eResult) {
		cout << XMLDocument::ErrorIDToName(eResult) << endl;
		exit(1);
	}

	XMLElement *root = xmlDoc.RootElement();
	XMLElement *name = root->FirstChildElement();
	XMLElement *comment = name->NextSiblingElement();

	cout << "name: " << name->GetText() << endl;
	cout << "comment: " << comment->GetText() << endl;

	XMLElement *images = root->FirstChildElement("images");
	XMLElement *image = images->FirstChildElement("image");
	const char *filename;

	while (image != nullptr) {
		image->QueryStringAttribute("file", &filename);
		cout << "filename: " << filename << endl;

		int top, left, width, height;
		XMLElement *box = image->FirstChildElement("box");
		while (box != nullptr) {
			box->QueryAttribute("top", &top);
			box->QueryAttribute("left", &left);
			box->QueryAttribute("width", &width);
			box->QueryAttribute("height", &height);

			cout << "\tBox: " << left << " "
							  << top << " "
							  << width << " "
							  << height << " "
							  << endl;

			box = box->NextSiblingElement();
		}

		image = image->NextSiblingElement();
	}

	return 0;
}

Output:


Cảm ơn các bạn đã theo dõi bài viết.
Thân ái và quyết thắng.

Reference:
[1] TinyXML2 library.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s