Nội dung bài viết
Đăng ký học lập trình C++
Tại STDIO bạn được dạy nền tảng lập trình tốt nhất.
Đăng ký học
Nguyễn Nghĩa Không thể phủ nhận được vai trò của XML trong quá trình phát triển ứng dụng. Thông thường được dùng để tạo rss, kết quả trả về từ server, lưu trữ dữ liệu...Vậy trong quá trình phát triển chúng ta cần phải thao tác khá là nhiều với những tài liệu XML này. Thì TinyXML là một trong những thư viện nhỏ gọn, hiệu quả, hổ trợ ngôn ngữ C++ giúp chúng ta làm được điều đó.

Giới thiệu

Không thể phủ nhận được vai trò của XML trong quá trình phát triển ứng dụng. Thông thường được dùng để tạo rss, kết quả trả về từ server, lưu trữ dữ liệu...Vậy trong quá trình phát triển chúng ta cần phải thao tác khá là nhiều với những tài liệu XML này. Thì TinyXML là một trong những thư viện nhỏ gọn, hiệu quả, hổ trợ ngôn ngữ C++ giúp chúng ta làm được điều đó.

Tiền đề bài viết

Trong quá trình thao tác với XML trong C++ tôi muốn tìm kiếm một thư viện để có thể sử dụng thay vì phải viết lại mã nguồn để thao tác. Tôi nhận thấy TinyXML là một thư viện hữu ích giúp chúc ta có thể làm việc được với tài liệu XML thông qua mô hình DOM (Document Object Model).

Đối tượng hướng đến

Những lập trình viên đang tìm hiểu một thư viện hổ trợ giúp chúng ta thao tác với tài liệu XML.

Cơ bản về XML

Cũng tương tự HTML là ngôn ngữ đánh dấu văn bản, nhưng XML một ưu điểm nổi là các thẻ đều do người dùng tự định nghĩa, không giống như HTML là phải tuân thủ theo các thẻ được xây dựng sẵn.

Ví dụ về HTML và XML:

HTML

<!DOCTYPE html>
<html>
	<head>
		<title>Tiêu đề </title>
	</head>
	<body>
		<p>Nội dung</p>
	</body>
</html>

XML

<?xml version="1.0" encoding="utf-8" ?>
<Authors>
    <Author id="01">Kevin La</Author>
    <Author id="268">Nguyen Nghia</Author>
</Authors>

Một ví dụ XML có cấu trúc phúc tạp hơn:

<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
</catalog>

Lưu ý: Tài liệu XML bắt buộc phải có một thẻ root. Thẻ root này sẽ chứa tất cả các thẻ con nằm trong nó. Thẻ root ở hai ví dụ trên là <authors></authors><catalog></catalog>.

Để hiểu rõ hơn về tài liệu XML các bạn có thể tham khảo bài viết Cơ Bản Về XML của tác giả Đinh Hòa.

Thư viện TinyXML

Giới thiệu

TinyXML là một thư viện mã nguồn mở C++, thao tác với tài liệu XML thông qua mô hình DOM (Document Object Model).

Phiên bản mới nhất của thư viện này là TinyXML 2.6.2. Các bạn có thể download thư viện tại ĐÂY.

Sơ đồ phân cấp lớp của thư viện này được mô tả như hình dưới đây:

ss_1

Với thông tin về mỗi lớp như sau:

Tên Class Thông tin về Class
TiXmlAttribute Đại diện cho thuộc tính, là một cặp name-value
TiXmlBase Là class cơ sở của tất cả mọi class trong TinyXML
TiXmlComment Đại diện cho comment trong tài liệu XML
TiXmlDeclaration Đại diện cho những khai báo ở đầu file trong tài liệu XML
TiXmlDocument Đại diện cho một tài liệu XML, chứa tất cả các thông tin về tài liệu này.
TiXmlElement Đại diện cho một node trong tài liệu XML
TiXmlNode Là class cơ sở trong mô hình DOM
TiXmlText Đại diện cho nội dung của một node trong tài liệu XML

Thêm thư viện vào Project

Tạo một Empty Project Console C++ với tên Project là Demo_TinyXML. Sau đó download thư viện ở trên và giải nén. Trong thư mục vừa mới giải nén ta chỉ quan tâm tới những file cần thiết là các file:

  • tinyxmlerror.cpp
  • tinyxmlparser.cpp
  • tinystr.cpp
  • tinystr.h
  • tinyxml.cpp
  • tinyxml.h

Copy những file này vào thư mục project của chúng ta.

ss_2

Sau đó thêm những file vào project trên Visual Studio bằng cách chuột phải (right-click) vào project chọn Add > Existing Item... và chọn những file trên và nhấn Add để kết thúc. Và kết quả sẽ như sau:

ss_3

Và thêm #include "tinyxml.h" vào đầu những file muốn sử dụng thư viện này:

#include "tinyxml.h"

Thao tác với tài liệu XML

Trong bài viết này tôi sẽ thao tác với tài liệu XML có nội dung như sau, việc thao tác với những tài liệu XML khác hoàn toàn tương tự.

<?xml version="1.0" encoding="utf-8" ?>
<!--Demo read, write, edit XML document using TinyXML library-->
<Authors>
	<Author id="01">
		<Name>Kevin La</Name>
		<Age>27</Age>
	</Author>
   	 <Author id="268">
		<Name>Nguyen Van Nghia</Name>
		<Age>20</Age>
	</Author>
</Authors>

Read

Tạo một file có tên là Authors.xml có nội dung như trên và copy file này vào thư mục project của chúng ta.

Các bước để đọc một tài liệu XML:

Bước 1: Load tài liệu lên bộ nhớ.

Bước 2: Lấy thông tin của node gốc (root element).

Bước 2: Lần lượt truy vấn qua các node con để lấy được thông tin cần thiết.

Đọc tài liệu Authors.xml như sau:

Load tài liệu:

TiXmlDocument doc("Authors.xml");
if (!doc.LoadFile())
{
	printf("%s", doc.ErrorDesc());
	return -1;
}

Lấy thông tin node gốc

TiXmlElement* root = doc.RootElement();

Truy vấn qua từng node và xuất thông tin:

int id;
//Tìm phần tử con đầu tiên của node roor
TiXmlElement* child1 = root->FirstChildElement();
//Lấy ra id của Author
child1->QueryIntAttribute("id", &id);
//Truy vấn đến phần tử con đầu tiên của child1
TiXmlElement* name = child1->FirstChildElement();
//Truy vấn đến phần tử tiếp theo cùng cấp name
TiXmlElement* age = name->NextSiblingElement();

//Xuất id
cout << id << " ";
//Xuất name
cout << name->GetText() << " ";
//Xuất age
cout << age->GetText() << endl;

//Truy xuất đến phần tử tiếp theo cùng cấp với child1
TiXmlElement* child2 = child1->NextSiblingElement();
//Lấy ra id của Author
child2->QueryIntAttribute("id", &id);
//Truy vấn đến phần tử con đầu tiên của child2
name = child2->FirstChildElement();
//Truy vấn đến phần tử tiếp theo cùng cấp name
age = name->NextSiblingElement();

//Xuất thông tin của author
cout << id << " ";
cout << name->GetText() << " ";
cout << age->GetText() << endl;

Kết quả:

ss_4

Giả sử có rất nhiều author, thì giải pháp tốt nhất là chúng ta sẽ sử dụng vòng lặp để duyệt qua tất cả các node:

TiXmlElement* author = nullptr;
int id;


for (author = root->FirstChildElement(); author != NULL; author = author->NextSiblingElement())
{
	author->QueryIntAttribute("id", &id);
	TiXmlElement* name = author->FirstChildElement();
	TiXmlElement* age = name->NextSiblingElement();
	cout << id << " ";
	cout << name->GetText() << " ";
	cout << age->GetText() << endl;
}

Các bạn có thể tìm hiểu rõ hơn về các phương thức FirstChild, LastChildPreviousSiblingNextSiblingNextSiblingElement để có thể truy vấn trong tài liệu XML một cách hiệu quả.

Write

Ở phần này tôi sẽ tạo lại một tài liệu XML có nội dung như Authors.xml nhưng lưu lại với tên là Author_Write.xml.

Tài liệu XML là một mô hình phân cấp. Nghĩa là một một node trong tài liệu XML đồng thời là cha của node này và là con của node kia. Ví dụ trong tài liệu Authors.xml thì Authors là cha của các Author, các Author là anh chị em với nhau. Mỗi Author đều có thuộc tính id và có hai con là Name Age. Cách tạo tài liệu XML cũng dựa trên điều này. Tạo ra các TiXmlElement và dùng phương thức có prototype như sau để thể hiện mối quan hệ trên:

TiXmlNode* TiXmlNode::LinkEndChild (TiXmlNode * addThis) 	

Tạo một đối tượng TiXmlDocument và thêm các node TiXmlDeclaration, TiXmlComment, đối tượng root TiXmlElement vào tài liệu này:

//Tạo đối tượng quản lý tài liệu XML
TiXmlDocument doc;

//Tạo chỉ thị của tài liệu XML bao gồm version, endcoding sau đó thêm dec vào tài liệu
TiXmlDeclaration *dec = new TiXmlDeclaration("1.0", "utf-8", "");
//Thêm dec vào tài liệu
doc.LinkEndChild(dec);

//Tạo comment và thêm comment vào tài liệu
TiXmlComment *cmt = new TiXmlComment("Demo read, write, edit XML document using TinyXML library");
doc.LinkEndChild(cmt);

//Tạo node root và thêm root vào tài liệu
TiXmlElement* root = new TiXmlElement("Authors");
doc.LinkEndChild(root);
	

Tạo hai đối tượng Author và thêm vào node root

//Tạo Author1
TiXmlElement* author1 = new TiXmlElement("Author");
//Set id cho author1
author1->SetAttribute("id", 1);
//Thêm author1 vào root
root->LinkEndChild(author1);


//Tạo Author2
TiXmlElement* author2 = new TiXmlElement("Author");
//Set id cho author2
author2->SetAttribute("id", 268);
//Thêm author2 vào root
root->LinkEndChild(author2);

Với mỗi Author ta sẽ tạo hai node là Name, Age và set nội dung cho chúng, sau đó add vào node author tương ứng.

Author1

//Tạo node Name 
TiXmlElement* author1_name = new TiXmlElement("Name");
author1->LinkEndChild(author1_name);
TiXmlText* name_content_1 = new TiXmlText("Kevin La");
author1_name->LinkEndChild(name_content_1);

//Tạo node Age
TiXmlElement* author1_age = new TiXmlElement("Age");
author1->LinkEndChild(author1_age);
TiXmlText* age_content_1 = new TiXmlText("27");
author1_age->LinkEndChild(age_content_1);
	

Author2

//Tạo node Name 
TiXmlElement* author2_name = new TiXmlElement("Name");
author2->LinkEndChild(author2_name);
TiXmlText* name_content_2 = new TiXmlText("Nguyen Van Nghia");
author2_name->LinkEndChild(name_content_2);

//Tạo node Age
TiXmlElement* author2_age = new TiXmlElement("Age");
author2->LinkEndChild(author2_age);
TiXmlText* age_content_2 = new TiXmlText("20");
author2_age->LinkEndChild(age_content_2);

Lưu tài liệu XML.

doc.SaveFile("Authors_Write.xml");

Dưới đây là toàn bộ souce code tại ra file Authors_Write.xml

//Tạo đối tượng quản lý tài liệu XML
TiXmlDocument doc;

//Tạo chỉ thị của tài liệu XML bao gồm version, endcoding sau đó thêm dec vào tài liệu
TiXmlDeclaration *dec = new TiXmlDeclaration("1.0", "utf-8", "");
//Thêm dec vào tài liệu
doc.LinkEndChild(dec);

//Tạo comment và thêm comment vào tài liệu
TiXmlComment *cmt = new TiXmlComment("Demo read, write, edit XML document using TinyXML library");
doc.LinkEndChild(cmt);

//Tạo node root và thêm root vào tài liệu
TiXmlElement* root = new TiXmlElement("Authors");
doc.LinkEndChild(root);
	

//Tạo Author1
TiXmlElement* author1 = new TiXmlElement("Author");
//Set id cho author1
author1->SetAttribute("id", 1);
//Thêm author1 vào root
root->LinkEndChild(author1);


//Tạo Author2
TiXmlElement* author2 = new TiXmlElement("Author");
//Set id cho author2
author2->SetAttribute("id", 268);
//Thêm author2 vào root
root->LinkEndChild(author2);

//Tạo node Name 
TiXmlElement* author1_name = new TiXmlElement("Name");
author1->LinkEndChild(author1_name);
TiXmlText* name_content_1 = new TiXmlText("Kevin La");
author1_name->LinkEndChild(name_content_1);

//Tạo node Age
TiXmlElement* author1_age = new TiXmlElement("Age");
author1->LinkEndChild(author1_age);
TiXmlText* age_content_1 = new TiXmlText("27");
author1_age->LinkEndChild(age_content_1);
	

//Tạo node Name 
TiXmlElement* author2_name = new TiXmlElement("Name");
author2->LinkEndChild(author2_name);
TiXmlText* name_content_2 = new TiXmlText("Nguyen Van Nghia");
author2_name->LinkEndChild(name_content_2);

//Tạo node Age
TiXmlElement* author2_age = new TiXmlElement("Age");
author2->LinkEndChild(author2_age);
TiXmlText* age_content_2 = new TiXmlText("20");
author2_age->LinkEndChild(age_content_2);

doc.SaveFile("Authors_Write.xml");

Build và chạy chương trình, sau đó mở thư mục chứa project các bạn sẽ thấy file Authors_Write.xml được tạo ra với nội dung giống như file Authors.xml.

Lời kết

Qua bài viết về thao tác với tài liệu XML sử dụng thư viện TinyXML, tôi đã hướng dẫn các bạn thao tác với tài liệu này. Hy vọng bài viết giúp ích cho các bạn. Nếu có bất cứ thắc mắc nào, các bạn có thể đưa ra những câu hỏi để tôi có thể giúp đỡ các bạn tốt nhất.

Tham khảo

http://www.grinninglizard.com/tinyxmldocs/annotated.html - 15/08/2015

Download demo

Demo_TinyXML_Stdio_VS2013.zip

THẢO LUẬN
ĐÓNG