Lessons X : Dùng DOM để display XML thành nhiều tầng trong TreeView

Logo of Vovisoft

Dùng DOM để display XML thành nhiều tầng trong TreeView

I nternet Explorer 5.0 cho ta Document Object Model (DOM) ActiveX gọi là MSXML.DLL mà ta có thể dùng trong VB6. Ðầu tiên là Microsoft XML, version 2.0, tiếp theo đó là Microsoft XML, v2.6 và mới nhất là Microsoft XML, v3.0. Cả ba DLL nầy đều có trong danh sách các References mà ta có thể include khi dùng IDE Menu command Project | References.
Khi ta Load một XML file vào DOM, nó tự động parse XML data để build một Tree gồm nhiều nodes với thứ bậc cha, con bên trong. Dựa theo đó ta có thể display cái DOM Tree ấy trong một TreeView để có thể hình dung được cấu trúc của XML data.

Trong thí dụ dưới đây, ta Load một XML file tên Library.xml vào DOM. XML file nầy còn có một Schema file tên LibrarySchema.xml. Khi DOM load XML file, ta có thể dặn nó kiểm (validate) xem XML data có theo đúng tiêu chuẩn đòi hỏi trong Schema file.
Content của Library.xml như sau, lưu ý hàng thứ 7 nhắc đến LibrarySchema.xml mà DOM sẽ dùng để validate data trong XML file:

<?xml version="1.0"?>
<?xml:stylesheet type="text/xsl" href="Library.xsl"?>
<!-- Copyright 2000 Wattle Software http://XMLwriter.net/ -->
<library xmlns="x-schema:LibrarySchema.xml">
   <!-- declare the Schema which defines this document -->
   <name>Northmead Local Library</name>
   <book hardback="yes" availableforloan="no">
      <title>C++ Programming for Beginners</title>
      <author>
         <first-name>Claude</first-name>
         <last-name>Schwartz</last-name>
      </author>
      <callno>005.133/C</callno>
      <online_url>http://library/online_books/005133C.html</online_url>
   </book>
   <journal series="XML Users Journal">
      <title>XML Users Journal August 1999</title>
      <date>1999-08-01</date>
      <callno>005.133/C</callno>
   </journal>
   <video>
      <title>Titanic</title>
      <director>
         <name>James Cameron</name>
      </director>
      <callno>643.11/T</callno>
   </video>
   <book>
      <title>The C Programming Language</title>
      <author>
         <first-name>Brian</first-name>
         <last-name>Kernighan</last-name>
      </author>
      <author>
         <first-name>Dennis</first-name>
         <last-name>Ritchie</last-name>
      </author>
      <callno>005.133/C2</callno>
      <online_url>http://library/online_books/005133C2.html</online_url>
   </book>
</library>


Content của LibrarySchema.xml như sau:

<?xml version="1.0"?>
<Schema xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes">
   <!-- Copyright 2000 Wattle Software http://XMLwriter.net/ This Schema is based on XML-Schema support found in Microsoft Internet Explorer 5. -->
   <!-- first we need to declare all elements that will appear only as child elements -->
   <ElementType name="first-name" content="textOnly"></ElementType>
   <ElementType name="last-name" content="textOnly"></ElementType>
   <ElementType name="name" content="textOnly"></ElementType>
   <ElementType name="price" content="textOnly" dt:type="fixed.14.4"></ElementType>
   <ElementType name="title" content="textOnly" dt:type="string"></ElementType>
   <ElementType name="artist" content="textOnly" dt:type="string"></ElementType>
   <ElementType name="callno" content="textOnly" dt:type="string"></ElementType>
   <ElementType name="date" content="textOnly" dt:type="date"></ElementType>
   <ElementType name="online_url" content="textOnly" dt:type="string"></ElementType>
   <!-- and all attributes too -->
   <AttributeType name="hardback" dt:type="string"></AttributeType>
   <AttributeType name="availableforloan" dt:type="string"></AttributeType>
   <AttributeType name="series" dt:type="string"></AttributeType>
   <!-- Now we can define the more interesting elements (i.e. those that can have children ) -->
   <ElementType name="author" content="eltOnly" order="one">
      <!-- An author can contain EITHER: a name, or a sequence of first-name then last-name -->
      <group order="seq">
         <element type="name"></element>
      </group>
      <group order="seq">
         <element type="first-name"></element>
         <element type="last-name"></element>
      </group>
   </ElementType>
   <ElementType name="director" content="eltOnly" order="one">
      <!-- A director can contain EITHER: a name, or a sequence of first-name then last-name -->
      <group order="seq">
         <element type="name"></element>
      </group>
      <group order="seq">
         <element type="first-name"></element>
         <element type="last-name"></element>
      </group>
   </ElementType>
   <ElementType name="video" content="eltOnly">
      <element type="title"></element>
      <element type="director"></element>
      <element type="callno"></element>
   </ElementType>
   <ElementType name="cd" content="eltOnly">
      <element type="title"></element>
      <element type="artist"></element>
      <element type="callno"></element>
   </ElementType>
   <ElementType name="journal" content="eltOnly">
      <!-- declare series as an optional attribute of journal -->
      <attribute type="series" required="no"></attribute>
      <element type="title"></element>
      <element type="date"></element>
      <element type="callno"></element>
   </ElementType>
   <ElementType name="book" content="eltOnly">
      <!-- declare hardback as an optional attribute of journal with default value of "no" -->
      <attribute type="hardback" default="no"></attribute>
      <attribute type="availableforloan" default="yes"></attribute>
      <element type="title"></element>
      <!-- allow for multiple authors with maxOccurs -->
      <element type="author" maxOccurs="*"></element>
      <element type="callno"></element>
      <!-- allow for ONE optional URL -->
      <element type="online_url" minOccurs="0" maxOccurs="1"></element>
   </ElementType>
   <ElementType name="library" content="eltOnly">
      <!-- the library name comes first -->
      <element type="name"></element>
      <!-- followed by a collection of books, videos and cds -->
      <group order="many">
         <element type="book" maxOccurs="*"></element>
         <element type="journal" maxOccurs="*"></element>
         <element type="video" maxOccurs="*"></element>
         <element type="cd" maxOccurs="*"></element>
      </group>
   </ElementType>
</Schema>


Việc đầu tiên khi chạy program là bạn click nút Load XML and Display in TreeView. Ðợi một chút xíu, Tree của XML sẽ hiện ra trong TreeView.
Ðồng thời Content của XML file cũng được loaded vào ListBox lstXMLSource và bạn sẽ thấy nó nếu bạn click Tab XML Source. Dĩ nhiên bạn có thể display bất cứ một XML file nào nếu bạn để nó vào folder của program và enter Filename của nó vào TextBox txtXMLFileName trứớc khi click nút Load XML and Display in TreeView.


Trong program nầy ta dùng Object IXMLDOMNode, thay vì Object IXMLDOMElement để lần lượt đi qua mọi nodes của XML DOM. Program gọi Sub AddNode để bỏ các Nodes vào TreeView. Ðặc biệt là AddNode gọi chính nó ở bên trong Sub AddNode. Kỹ thuật nầy gọi là recursive, mà ta thường lấy dùng trong những cấu trúc giống như nhánh cây, khi chính một Con lại có nhiều Con khác. Listing của Sub AddNode như sau:

Private Sub AddNode(ByRef oElem As IXMLDOMNode, Optional ByRef oTreeNode As Node) 
   ' Add a Node to the TreeView
   Dim oNewNode As Node 
   Dim oNodeList As IXMLDOMNodeList 
   Dim i As Long 
   ' Create the new node
   If oTreeNode Is Nothing Then 
      ' Go through here when creating the top level nodes, i.e. childNodes of root node
      Set oNewNode = TreeView.Nodes.Add 
   Else 
      Set oNewNode = TreeView.Nodes.Add(oTreeNode, tvwChild) 
   End If 
   ' Expand TreeView node
   oNewNode.Expanded = True 
   ' Prepare the Text for the TreeView Node
   If oElem.nodeType = NODE_ELEMENT Then 
      ' Element Node type. Use Node name and Attribute values
      oNewNode.Text = BuildNodeLabel(oElem) 
   ElseIf (oElem.nodeType = NODE_TEXT) Then 
      ' Last Node in the branch. Use Text
      oNewNode.Text = oElem.Text 
   ElseIf (oElem.nodeType = NODE_COMMENT) Then 
      ' Comment Node. Display the comment
      oNewNode.Text = "Comment:" & oElem.Text 
   Else 
      ' Display Nodename as default
      oNewNode.Text = oElem.nodeName 
   End If 
   ' process the childNodes which form a NodeList
   Set oNodeList = oElem.childNodes 
   ' Iterate through each childNode
   For i = 0 To oNodeList.length - 1 
      ' Recursively call AddNode to add more nodes as children of oNewNode,
      ' treating AddNode just like another Sub
      AddNode oNodeList.Item(i), oNewNode 
   Next 
End Sub


Có ba loại Nodes ta xử lý ở đây: NODE_ELEMENT, NODE_TEXT và NODE_COMMENT. Element Node thì có Node , Attributes và Con. Text Node và Comment Node thì chỉ có text.

Bạn có thể download chương trình mẫu XMLTreeDOM.zip để chạy thử.

Ðể biết thêm các Properties và Methods của các Classes trong MSXML, từ trong VB6 IDE bạn press F2 để display Object Browser. Khi Object Browser Dialog hiện ra, chọn MSXML2 từ ComboBox phía trên đang display <All Libraries>, kế đó chọn một class, thí dụ như IXMLDOMNode từ ListBox bên trái, chi tiết của selected Class sẽ được displayed trong ListBox bên phải như trong hình dưới đây:

  Kỹ thuật XML

 

  1. Leave a comment

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: