Operations on XML Elements |
|
Creating an XML Element
Introduction
The IXMLDOMNode interface provides the properties and methods used to perform most routine operations of an XML document. The operations include locating a node, adding a new tag, or deleting an element.
Before performing an operation, you will usually need to decide in what section of the document you want the action to be applied. As it happens, you have the root node, a particular node inside the document, the parent of a node, the sibling of a node, etc. To get to a node, you will usually first get a reference to its IXMLDOMNode object. To do this, you can declare an IXMLDOMNode variable, call a method that returns that reference, and initialize the variable with it. You can get a reference when creating an element. Here is an example:
Private Sub cmdCreate_Click()
Dim docXMLDOM As DOMDocument
Dim nodElement As IXMLDOMElement
Set docXMLDOM = New DOMDocument
Set nodElement = docXMLDOM.createElement("videos")
Set docXMLDOM.documentElement = nodElement
docXMLDOM.Save "C:\Exercises\videos2.xml"
Set docXMLDOM = Nothing
End Sub
This would produce:
<?xml version="1.0"?>
<videos></videos>
You can also get a reference after locating the desired element.
Appending an Element
We already saw that, to let you create a new element, the DOMDocument class provides the createElement() method. Using this method, to create a new element, call it and pass it the name of the element. We already know that the createElement() method belongs to the DOMDocument class. To let you create an element as either a child of the root node or a child of any other element, the IXMLDOMNode interface is equipped with a method named appendChild. The syntax of the IXMLDOMNode.appendChild() method is:
Public Function appendChild(ByVal newChild As IXMLDOMNode) As IXMLDOMNode
When calling this method, pass an IXMLDOMNode object you would have previously created. Here is an example:
Private Sub cmdAppendElement_Click()
Dim docXMLDOM As DOMDocument
Dim nodElement As IXMLDOMElement
Dim nodChild As IXMLDOMElement
Set docXMLDOM = New DOMDocument
Set nodElement = docXMLDOM.createElement("videos")
Set docXMLDOM.documentElement = nodElement
Set nodChild = docXMLDOM.createElement("video")
nodElement.appendChild nodChild
docXMLDOM.Save "C:\Exercises\videos3.xml"
Set docXMLDOM = Nothing
End Sub
This would produce:
<?xml version="1.0"?>
<videos>
<video></video>
</videos>
In the same way, you can create other child nodes of the root. Simply use a combination of calling the DOMDocument.createElement() method that initializes IXMLDOMElement element you want to create, and calling the IXMLDOMNode.appendChild() method to which you pass a reference of the IXMLDOMElement variable. Here are examples:
Private Sub cmdAppendElement_Click()
Dim docXMLDOM As DOMDocument
Dim nodElement As IXMLDOMElement
Dim nodChild As IXMLDOMElement
Set docXMLDOM = New DOMDocument
Set nodElement = docXMLDOM.createElement("Videos")
Set docXMLDOM.documentElement = nodElement
Set nodChild = docXMLDOM.createElement("Video")
nodElement.appendChild nodChild
Set nodChild = docXMLDOM.createElement("Video")
nodElement.appendChild nodChild
Set nodChild = docXMLDOM.createElement("Video")
nodElement.appendChild nodChild
docXMLDOM.Save "C:\Exercises\videos4.xml"
Set docXMLDOM = Nothing
End Sub
This would produce:
<?xml version="1.0"?>
<Videos>
<Video></Video>
<Video></Video>
<Video></Video>
</Videos>
Notice that, if you simply call the IXMLDOMNode.appendChild() method to create an element, the newly added element is empty. If you want the new node to have a value, assign the desired string to its Text property. Here is an example:
Private Sub cmdAppendElement_Click()
Dim docXMLDOM As DOMDocument
Dim nodChild As IXMLDOMElement
Dim nodElement As IXMLDOMElement
Set docXMLDOM = New DOMDocument
Set nodElement = docXMLDOM.createElement("Videos")
Set docXMLDOM.documentElement = nodElement
Set nodChild = docXMLDOM.createElement("Video")
nodChild.Text = "Basic Instinct"
nodElement.appendChild nodChild
docXMLDOM.Save "C:\Exercises\videos5.xml"
Set docXMLDOM = Nothing
End Sub
This would produce:
<?xml version="1.0"?>
<Videos>
<Video>Basic Instinct</Video>
</Videos>
In the same way, you can add a value to any other element you are creating. If you want to create a processing instruction, declare its variable, call the DOMDocument.createProcessingInstruction() method, then call the DOMDocument.appendChild() method. Here is an example:
Private Sub cmdCreateElement_Click() Dim docXMLDOM As Object Dim nodElement As Object Dim piDeclaration As Object Set docXMLDOM = CreateObject("MSXML2.DOMDocument.3.0") Set piDeclaration = docXMLDOM.createProcessingInstruction("xml", "version='1.0'") docXMLDOM.appendChild piDeclaration Set nodElement = docXMLDOM.createElement("houses") Set docXMLDOM.documentElement = nodElement docXMLDOM.Save "C:\Exercises\Houses2.xml" Set docXMLDOM = Nothing End Sub
This would produce:
<?xml version="1.0"?>
<houses></houses>
Creating Child Nodes
One one hand, the DOMDocument.createElement() method is used to start a new node. On the other hand, the IXMLDOMNode.appendChild() method is used to add a child node to an element. Also, the call to IXMLDOMNode.appendChild() produces a reference to the new child node. If you want to create a child of that new node, after declaring an IXMLDOMElement variable, initialize it with a call to DOMDocument.createElement(). Then call the IXMLDOMNode.appendChild() method of its parent and pass your new node as argument. Here is an example:
Private Sub cmdCreateChildNodes_Click()
Dim docXMLDOM As DOMDocument
Dim nodElement As IXMLDOMElement
Dim nodChild As IXMLDOMElement
Dim nodGrandChild As IXMLDOMElement
Set docXMLDOM = New DOMDocument
Set nodElement = docXMLDOM.createElement("Videos")
Set docXMLDOM.documentElement = nodElement
Set nodChild = docXMLDOM.createElement("video")
nodElement.appendChild nodChild
Set nodGrandChild = docXMLDOM.createElement("title")
nodChild.appendChild nodGrandChild
docXMLDOM.Save "C:\Exercises\videos6.xml"
Set docXMLDOM = Nothing
End Sub
This would produce:
<?xml version="1.0"?>
<videos>
<video>
<title></title>
</video>
</videos>
In the same way, you can create other child nodes of an element. Here are examples:
Private Sub cmdCreateChildNodes_Click() Dim docXMLDOM As DOMDocument Dim nodElement As IXMLDOMElement Dim nodChild As IXMLDOMElement Dim nodGrandChild As IXMLDOMElement Set docXMLDOM = New DOMDocument Set nodElement = docXMLDOM.createElement("Videos") Set docXMLDOM.documentElement = nodElement Set nodChild = docXMLDOM.createElement("Video") nodElement.appendChild nodChild Set nodGrandChild = docXMLDOM.createElement("Title") nodChild.appendChild nodGrandChild Set nodGrandChild = docXMLDOM.createElement("Director") nodChild.appendChild nodGrandChild Set nodChild = docXMLDOM.createElement("Video") nodElement.appendChild nodChild Set nodGrandChild = docXMLDOM.createElement("Director") nodChild.appendChild nodGrandChild Set nodGrandChild = docXMLDOM.createElement("Length") nodChild.appendChild nodGrandChild Set nodGrandChild = docXMLDOM.createElement("Rating") nodChild.appendChild nodGrandChild Set nodGrandChild = docXMLDOM.createElement("Title") nodChild.appendChild nodGrandChild Set nodChild = docXMLDOM.createElement("Video") nodElement.appendChild nodChild Set nodGrandChild = docXMLDOM.createElement("Rating") nodChild.appendChild nodGrandChild docXMLDOM.Save "C:\Exercises\videos7.xml" Set docXMLDOM = Nothing End Sub
This would produce:
<Videos> <Video> <Title></Title> <Director></Director> </Video> <Video> <Director></Director> <Length></Length> <Rating></Rating> <Title></Title> </Video> <Video> <Rating></Rating> </Video> </Videos>
In the same way, you can create grand child nodes nested in child nodes of elements. Here are examples:
Private Sub cmdCreateChildNodes_Click() Dim docXMLDOM As DOMDocument Dim nodElement As IXMLDOMElement Dim nodChild As IXMLDOMElement Dim nodGrandChild As IXMLDOMElement Dim nodGreatGrandChild As IXMLDOMElement Dim nodGreatGreatGrandChild As IXMLDOMElement Set docXMLDOM = New DOMDocument Set nodElement = docXMLDOM.createElement("Videos") Set docXMLDOM.documentElement = nodElement Set nodChild = docXMLDOM.createElement("Video") nodElement.appendChild nodChild Set nodGrandChild = docXMLDOM.createElement("Title") nodChild.appendChild nodGrandChild Set nodGreatGrandChild = docXMLDOM.createElement("CastMembers") nodGrandChild.appendChild nodGreatGrandChild Set nodGrandChild = docXMLDOM.createElement("Director") nodChild.appendChild nodGrandChild Set nodChild = docXMLDOM.createElement("Video") nodElement.appendChild nodChild Set nodGrandChild = docXMLDOM.createElement("Director") nodChild.appendChild nodGrandChild Set nodGrandChild = docXMLDOM.createElement("Length") nodChild.appendChild nodGrandChild Set nodGrandChild = docXMLDOM.createElement("Rating") nodChild.appendChild nodGrandChild Set nodGrandChild = docXMLDOM.createElement("Title") nodChild.appendChild nodGrandChild Set nodGreatGrandChild = docXMLDOM.createElement("Actors") nodGrandChild.appendChild nodGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("Actor") nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("Actor") nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodChild = docXMLDOM.createElement("Video") nodElement.appendChild nodChild Set nodGreatGrandChild = docXMLDOM.createElement("TechnicalTeam") nodGrandChild.appendChild nodGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("LineProducer") nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("FirstAssistantDirector") nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("SecondAssistantDirector") nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodGrandChild = docXMLDOM.createElement("Rating") nodChild.appendChild nodGrandChild docXMLDOM.Save "C:\Exercises\videos8.xml" Set docXMLDOM = Nothing End Sub
This would produce:
<Videos> <Video> <Title> <CastMembers></CastMembers> </Title> <Director></Director> </Video> <Video> <Director></Director> <Length></Length> <Rating></Rating> <Title> <Actors> <Actor></Actor> <Actor></Actor> </Actors> <TechnicalTeam> <LineProducer></LineProducer> <FirstAssistantDirector></FirstAssistantDirector> <SecondAssistantDirector></SecondAssistantDirector> </TechnicalTeam> </Title> </Video> <Video> <Rating></Rating> </Video> </Videos>
Remember that, to specify the value of a node, assign the desired string to its Text property. Here are examples:
Private Sub cmdCreate_Click() Dim docXMLDOM As DOMDocument Dim nodElement As IXMLDOMElement Dim nodChild As IXMLDOMElement Dim nodGrandChild As IXMLDOMElement Dim nodGreatGrandChild As IXMLDOMElement Dim nodGreatGreatGrandChild As IXMLDOMElement Set docXMLDOM = New DOMDocument Set nodElement = docXMLDOM.createElement("Videos") Set docXMLDOM.documentElement = nodElement Set nodChild = docXMLDOM.createElement("Video") nodElement.appendChild nodChild Set nodGrandChild = docXMLDOM.createElement("Title") nodChild.appendChild nodGrandChild Set nodGreatGrandChild = docXMLDOM.createElement("CastMembers") nodGrandChild.appendChild nodGreatGrandChild Set nodGrandChild = docXMLDOM.createElement("Director") nodChild.appendChild nodGrandChild Set nodChild = docXMLDOM.createElement("Video") nodElement.appendChild nodChild Set nodGrandChild = docXMLDOM.createElement("Director") nodChild.appendChild nodGrandChild nodGrandChild.Text = "Jonathan Lynn" Set nodGrandChild = docXMLDOM.createElement("Length") nodGrandChild.Text = "112 Minutes" nodChild.appendChild nodGrandChild Set nodGrandChild = docXMLDOM.createElement("Rating") nodGrandChild.Text = "R" nodChild.appendChild nodGrandChild Set nodGrandChild = docXMLDOM.createElement("Title") nodGrandChild.Text = "The Distinguished Gentleman" nodChild.appendChild nodGrandChild Set nodGreatGrandChild = docXMLDOM.createElement("Actors") nodGrandChild.appendChild nodGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("Actor") nodGreatGreatGrandChild.Text = "Eddie Murphy" nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("Actor") nodGreatGreatGrandChild.Text = "Lane Smith" nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("Actor") nodGreatGreatGrandChild.Text = "Sheryl Lee Ralph" nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodChild = docXMLDOM.createElement("Video") nodElement.appendChild nodChild Set nodGreatGrandChild = docXMLDOM.createElement("TechnicalTeam") nodGrandChild.appendChild nodGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("LineProducer") nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("FirstAssistantDirector") nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodGreatGreatGrandChild = docXMLDOM.createElement("SecondAssistantDirector") nodGreatGrandChild.appendChild nodGreatGreatGrandChild Set nodGrandChild = docXMLDOM.createElement("Rating") nodChild.appendChild nodGrandChild docXMLDOM.Save "C:\Exercises\videos9.xml" Set docXMLDOM = Nothing End Sub
This would produce:
<Videos> <Video> <Title> <CastMembers></CastMembers> </Title> <Director></Director> </Video> <Video> <Director>Jonathan Lynn</Director> <Length>112 Minutes</Length> <Rating>R</Rating> <Title>The Distinguished Gentleman</Title> <Actors> <Actor>Eddie Murphy</Actor> <Actor>Lane Smith</Actor> <Actor>Sheryl Lee Ralph</Actor> </Actors> <TechnicalTeam> <LineProducer></LineProducer> <FirstAssistantDirector></FirstAssistantDirector> <SecondAssistantDirector></SecondAssistantDirector> </TechnicalTeam> </Title> </Video> <Video> <Rating></Rating> </Video> </Videos>
Consider the following XML document:
<?xml version="1.0" encoding="utf-8"?> <videos> <video> <title>The Distinguished Gentleman</title> </video> <video> <title>Basic Instinct</title> </video> </videos>
If you want to add a new node to the root of such an element, first get a reference to the root node using the documentElement property of the root node. To create the new element, call the DOMDocument.createElement() method to create the start tag. Then call the IXMLDOMNode.appendChild() method on the root node. Here is an example::
Private Sub cmdCreate_Click() Dim docXMLDOM As DOMDocument Dim nodRoot As IXMLDOMElement Dim nodElement As IXMLDOMElement Set docXMLDOM = New DOMDocument docXMLDOM.Load "C:\Exercises\Videos10.xml" Set nodRoot = docXMLDOM.documentElement Set nodElement = docXMLDOM.createElement("video") nodRoot.appendChild nodElement docXMLDOM.Save "C:\Exercises\videos10.xml" Set docXMLDOM = Nothing End Sub
This would produce:
<?xml version="1.0" encoding="utf-8" ?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
</video>
<video>
<title>Basic Instinct</title>
</video>
<Video></Video>
</videos>
The call to IXMLDOMNode.appendChild() produces a reference to the new child node. If you want to create a child of that new node, after declaring an IXMLDOMElement variable, initialize it with a call to DOMDocument.createElement(). Then call theIXMLDOMNode.appendChild() method of its parent and pass your new node as argument.Here is an example of how you would do this:
Private Sub cmdCreate_Click() Dim docXMLDOM As DOMDocument Dim nodRoot As IXMLDOMElement Dim nodElement As IXMLDOMElement Dim nodChild As IXMLDOMElement Set docXMLDOM = New DOMDocument docXMLDOM.Load "C:\Exercises\videos10.xml" Set nodRoot = docXMLDOM.documentElement Set nodElement = docXMLDOM.createElement("Video") nodRoot.appendChild nodElement Set nodChild = docXMLDOM.createElement("Title") nodElement.appendChild nodChild docXMLDOM.Save "C:\Exercises\Videos10.xml" Set docXMLDOM = Nothing End Sub
This would produce:
<?xml version="1.0" encoding="utf-8" ?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
</video>
<video>
<title>Basic Instinct</title>
</video>
<Video>
<Title></Title>
</Video>
</videos>
By now, you should know how easy it is to specify the value of an element: assign the desired string to its Text property. Just in case, here is an example:
Private Sub cmdCreate_Click()
Dim docXMLDOM As DOMDocument
Dim nodRoot As IXMLDOMElement
Dim nodElement As IXMLDOMElement
Dim nodChild As IXMLDOMElement
Set docXMLDOM = New DOMDocument
docXMLDOM.Load "C:\Exercises\videos10.xml"
Set nodRoot = docXMLDOM.documentElement
Set nodElement = docXMLDOM.createElement("Video")
nodRoot.appendChild nodElement
Set nodChild = docXMLDOM.createElement("Title")
nodChild.Text = "Her Alibi"
nodElement.appendChild nodChild
docXMLDOM.Save "C:\Exercises\Videos10.xml"
Set docXMLDOM = Nothing
End Sub
This would produce:
<?xml version="1.0" encoding="utf-8"?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
</video>
<video>
<title>Basic Instinct</title>
</video>
<video>
<title>Her Alibi</title>
</video>
</videos>
In the same way, you can create child and grant-child (and great-grand child) nodes.
Locating an Element
Introduction
In some cases, you may want to perform an operation on an existing and particular node. For example, you may want to change the value of a node, you may want to add a new child node to an existing node, etc. Before taking any of these actions, you must be able to locate or identify the desired element.
Locating an element consists of looking for a particular node among the nodes. To do this, you must start somewhere. Obviously, the first node you can identify is the root. Once you get the root, you can then get a collection of its children. After getting a collection of the children of the root, you can locate a node in the collection. If the node you are looking for is a child of that first collection, you can then get a collection of the child nodes of that node and proceed.
Locating an Element Using its Index
Consider the following XML file named videos12.xml:
<?xml version="1.0" encoding="utf-8"?> <videos> <video> <title>The Distinguished Gentleman</title> <director>Jonathan Lynn</director> <length>112 Minutes</length> <format>DVD</format> <rating>R</rating> </video> <video> <title>Her Alibi</title> <director>Bruce Beresford</director> <length>94 Minutes</length> <format>DVD</format> <rating>PG-13</rating> </video> <video> <title>The Day After Tomorrow</title> <director>Roland Emmerich</director> <length>124 Minutes</length> <format>DVD</format> <rating>PG-13</rating> </video> <video> <title>Other People's Money</title> <director>Alan Brunstein</director> <length>114 Minutes</length> <format>VHS</format> <rating>PG-13</rating> </video> </videos>
We saw that the IXMLDOMNodeList interface is equipped with an indexed property named Item. That member allows you to access an element based on its index. Here are examples:
Private Sub cmdLocate_Click() Dim docXMLDOM As DOMDocument Dim nodRoot As IXMLDOMElement Dim lstVideos As IXMLDOMNodeList Set docXMLDOM = New DOMDocument docXMLDOM.Load "C:\Exercises\videos12.xml" Set nodRoot = docXMLDOM.documentElement Set lstVideos = nodRoot.childNodes MsgBox lstVideos(0).Text MsgBox lstVideos(0).XML Set docXMLDOM = Nothing End Sub
This would produce:
You can use this characteristic to locate a node. Because XML is very flexible with the names (you can have two child nodes that have the same name) and values (you can have two child nodes that have the same value) of nodes, when creating an XML file, it is your responsibility to create a scheme that would eventually allow you to uniquely identify each element.
Locating an Element Using a Tag Name
To assist you with finding a node, the DOMDocument class is equipped with a method named getElementByTagName. Its syntax is:
Public Function getElementsByTagName(ByVal tagName As String) As IXMLDOMNodeList
This method takes as argument the name of a node as a string. If at least one node that holds that name exists in the document, this method returns a collection of the nodes with that name. If there is no node with that name, the collection is returned empty. Here is an example of calling the method:
Private Sub cmdLocate_Click() Dim docXMLDOM As DOMDocument Dim nodRoot As IXMLDOMElement Dim lstVideos As IXMLDOMNodeList Set docXMLDOM = New DOMDocument docXMLDOM.Load "C:\Exercises\videos12.xml" Set nodRoot = docXMLDOM.documentElement Set lstVideos = nodRoot.getElementsByTagName("title") Set docXMLDOM = Nothing End Sub
Once you have a list of the nodes of a particular criterion, you can then act as you see fit. For example, For example, you can look for a particular node that holds a text of your choice.
Techniques of Creating Elements Adding an Element as a Child Consider the following document from a file named videos13.xml file: <?xml version="1.0" encoding="utf-8"?> <videos> <video> <title>The Distinguished Gentleman</title> <director>Jonathan Lynn</director> <length>112 Minutes</length> <format>DVD</format> <rating>R</rating> </video> <video> <title>Her Alibi</title> <director>Bruce Beresford</director> <length>94 Minutes</length> <format>DVD</format> <rating>PG-13</rating> </video> <video> <title>The Day After Tomorrow</title> <director>Roland Emmerich</director> <length>124 Minutes</length> <format>DVD</format> <rating>PG-13</rating> </video> <video> <title>Other People's Money</title> <director>Alan Brunstein</director> <length>114 Minutes</length> <format>VHS</format> <rating>PG-13</rating> </video> </videos> Imagine you want to create a new node as a child of one of the elements. The first action to take is to locate the element that will act as the parent. If/since you know the element, you can locate it using its name by calling the DOMDocument.getElementsByTagName() method applied to a collection of nodes. From that list of nodes, you can look for the node whose value you know. Once you have found this element, get a reference to its parent. Then add the new node as a child to its parent. This can be done as follows: Private Sub cmdInsertElement_Click() Dim Found As Boolean Dim docXMLDOM As DOMDocument Dim nodChild As IXMLDOMElement Dim nodParent As IXMLDOMElement Dim nodElement As IXMLDOMElement Dim lstVideos As IXMLDOMNodeList Found = False Set docXMLDOM = New DOMDocument docXMLDOM.Load "C:\Exercises\videos13.xml" Set lstVideos = docXMLDOM.getElementsByTagName("title") For Each nodElement In lstVideos If nodElement.Text = "Her Alibi" Then Set nodChild = docXMLDOM.createElement("actors") Set nodParent = nodElement.parentNode nodParent.appendChild nodChild docXMLDOM.Save "C:\Exercises\Videos13.xml" Found = True End If Next If Found = False Then MsgBox "There is no element with that value", _ vbOKOnly Or vbInformation, _ "Extensible Markup Language" End If Set docXMLDOM = Nothing End Sub This would produce: <?xml version="1.0" encoding="utf-8"?>
<videos>
. . .
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
<actors></actors>
</video>
. . .
</videos>
This code creates an empty element. You may already know how to specify the value of an element: by assigning a string to its Text property. Here is an example: Private Sub cmdInsertElement_Click()
Dim Found As Boolean
Dim docXMLDOM As DOMDocument
Dim nodChild As IXMLDOMElement
Dim nodParent As IXMLDOMElement
Dim nodElement As IXMLDOMElement
Dim lstVideos As IXMLDOMNodeList
Found = False
Set docXMLDOM = New DOMDocument
docXMLDOM.Load "C:\Exercises\videos13.xml"
Set lstVideos = docXMLDOM.getElementsByTagName("title")
For Each nodElement In lstVideos
If nodElement.Text = "The Day After Tomorrow" Then
Set nodChild = docXMLDOM.createElement("category")
nodChild.Text = "Drama - Environment"
Set nodParent = nodElement.parentNode
nodParent.appendChild nodChild
docXMLDOM.Save "C:\Exercises\Videos13.xml"
Found = True
End If
Next
If Found = False Then
MsgBox "There is no element with that value", _
vbOKOnly Or vbInformation, _
"Extensible Markup Language"
End If
Set docXMLDOM = Nothing
End Sub
This would produce: <?xml version="1.0" encoding="utf-8" ?>
<videos>
. . .
<video>
<title>The Day After Tomorrow</title>
<director>Roland Emmerich</director>
<length>124 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
<category>Drama - Environment</category>
</video>
. . .
</videos>
Creating an Element Before a Node MSXML makes it possible to programmatically add a new element based on the position of another. For example, you can create a new node before an existing one. To support this operation, the IXMLDOMNodeList interface is equipped with a method named insertBefore. Its syntax is: public Function insertAfter(ByVal newChild As IXMLDOMNodeList, _ ByVal refChild As IXMLDOMNodeList) As IXMLDOMNodeList This function takes two arguments. The first argument is the element you want to create. The second argument is the node that will precede the one you are creating. Consider the following XML file named videos.xml: <?xml version="1.0" encoding="utf-8"?> <videos> <video> <title>The Distinguished Gentleman</title> <director>Jonathan Lynn</director> <length>112 Minutes</length> <format>DVD</format> <rating>R</rating> </video> <video> <title>Her Alibi</title> <director>Bruce Beresford</director> <length>94 Minutes</length> <format>DVD</format> <rating>PG-13</rating> </video> </videos> Imagine you want to add a new element before the second one. Here is an example of how this can be done: Private Sub cmdInsertElement_Click()
Dim Found As Boolean
Dim docXMLDOM As DOMDocument
Dim nodRoot As IXMLDOMElement
Dim nodElement As IXMLDOMElement
Dim lstVideos As IXMLDOMNodeList
Dim nodNewElement As IXMLDOMElement
Dim nodReference As IXMLDOMElement
' Initialize the document model
Set docXMLDOM = New DOMDocument
' Open the XML document
docXMLDOM.Load "C:\Exercises\videos14.xml"
' Get a list of nodes based on the director element
Set lstVideos = docXMLDOM.getElementsByTagName("title")
' Check the list of all nodes
For Each nodElement In lstVideos
' If you find a video titled Her Alibi, ...
If nodElement.Text = "Her Alibi" Then
' ... get a reference to that video
Set nodReference = nodElement
' Let the interpreter know that we found a match
Found = True
' Get out of the For loop (no need to look further)
Exit For
End If
Next
' Since the video was found
If Found = True Then
' Get a reference to the root node
Set nodRoot = docXMLDOM.documentElement
' ... start a new node named video
Set nodNewElement = docXMLDOM.createElement("video")
' Add the new node before the element titled video
nodRoot.insertBefore nodNewElement, nodReference.parentNode
' Save the file
docXMLDOM.Save "C:\Exercises\Videos14.xml"
End If
Set docXMLDOM = Nothing
End Sub
This would produce: <?xml version="1.0" encoding="utf-8" ?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
<video></video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
</videos>
If you want, you can then populate the new node with a value and/or child nodes. Here are examples from the original videos14.xml file: Private Sub cmdInsertElement_Click() Dim docXMLDOM As DOMDocument Dim nodRoot As IXMLDOMElement Dim nodChild As IXMLDOMElement Dim nodElement As IXMLDOMElement Dim lstVideos As IXMLDOMNodeList Dim nodReference As IXMLDOMElement Dim nodNewElement As IXMLDOMElement ' Initialize the document model Set docXMLDOM = New DOMDocument ' Open the XML document docXMLDOM.Load "C:\Exercises\videos14.xml" ' Get a list of nodes based on the director element Set lstVideos = docXMLDOM.getElementsByTagName("title") ' Check the list of all nodes For Each nodElement In lstVideos ' If you find a video titled Her Alibi, ... If nodElement.Text = "Her Alibi" Then ' ... get a reference to that video Set nodReference = nodElement ' Get a reference to the root node Set nodRoot = docXMLDOM.documentElement ' ... start a new node named video Set nodNewElement = docXMLDOM.createElement("video") ' Specify some value for the element nodNewElement.Text = "The video is provided in Blu-ray/DVD Combo." ' Add some child nodes to the new element Set nodChild = docXMLDOM.createElement("title") nodChild.Text = "A Good Day to Die Hard" nodNewElement.appendChild nodChild Set nodChild = docXMLDOM.createElement("director") nodChild.Text = "John Moore" nodNewElement.appendChild nodChild Set nodChild = docXMLDOM.createElement("length") nodChild.Text = "98 minutes" nodNewElement.appendChild nodChild ' Add the new node before the referenced element nodRoot.insertBefore nodNewElement, nodReference.parentNode ' Save the file docXMLDOM.Save "C:\Exercises\Videos14.xml" ' Get out of the For loop (no need to look further) Exit For End If Next Set docXMLDOM = Nothing End Sub This would produce: <?xml version="1.0" encoding="utf-8" ?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
<video>The video is provided in Blu-ray/DVD Combo.
<title>A Good Day to Die Hard</title>
<director>John Moore</Director>
<length>98 minutes</length>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
</videos>
Of course, you can also add an element before a node that is a child node. Here is an example: Private Sub cmdInsertElement_Click()
Dim docXMLDOM As DOMDocument
Dim nodElement As IXMLDOMElement
Dim lstVideos As IXMLDOMNodeList
Dim nodNewElement As IXMLDOMElement
' Initialize the document model
Set docXMLDOM = New DOMDocument
' Open the XML document
docXMLDOM.Load "C:\Exercises\videos14.xml"
' Get a list of nodes based on the director element
Set lstVideos = docXMLDOM.getElementsByTagName("director")
' Check the list of all nodes
For Each nodElement In lstVideos
' If you find a director named Jonathan Lynn, ...
If nodElement.Text = "Jonathan Lynn" Then
' ... start a new node named actors
Set nodNewElement = docXMLDOM.createElement("actors")
' Add the new node before the element named director
nodElement.parentNode.insertBefore nodNewElement, nodElement
' Save the file
docXMLDOM.Save "C:\Exercises\Videos14.xml"
Exit For
End If
Next
Set docXMLDOM = Nothing
End Sub
This would produce: <?xml version="1.0" encoding="utf-8" ?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<actors></actors>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
</videos>
Remember that you can specify the value of an element by assigning a string to its Text property. You can also add child nodes to the new element. For some reason, the MSXML library in Microsoft Access does not have a function to "insert after", but you should be able to easily perform such an operation (or you can create the function yourself). Replacing a Child Node of an Element If you have an existing node but that has a wrong child node (probably the name of the child node is wrong) or a child node has a wrong value, you can edit the child node or change the value of the child node(s). This is done by creating a new value and replacing the existing one. To support this operation, the IXMLDOMNodeList interface is equipped with a method named replaceChild. Its syntax is: Public Function replaceChild(ByVal newChild As IXMLDOMNode, _ ByVal oldChild As IXMLDOMNode) As IXMLDOMNode This mehod takes as arguments the new child node that will replace the existing element. Consider the following XML file named videos15.xml <?xml version="1.0" encoding="utf-8" ?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
<video>The video is provided in Blu-ray/DVD Combo.
<title>A Good Day to Die Hard</title>
<director>John Moore</Director>
<length>98 minutes</length>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
</videos>
Imagine you want to completely replace the video in the middle: A Good Day to Die Hard. Here is an example that replaces an existing node with a new one: Private Sub cmdReplaceElement_Click() Dim docXMLDOM As DOMDocument Dim nodRoot As IXMLDOMElement Dim nodChild As IXMLDOMElement Dim nodElement As IXMLDOMElement Dim lstVideos As IXMLDOMNodeList Dim nodReference As IXMLDOMElement Dim nodNewElement As IXMLDOMElement ' Initialize the document model Set docXMLDOM = New DOMDocument ' Open the XML document docXMLDOM.Load "C:\Exercises\videos15.xml" ' Get a list of nodes based on the director element Set lstVideos = docXMLDOM.getElementsByTagName("title") ' Check the list of all nodes For Each nodElement In lstVideos ' If you find a video titled Her Alibi, ... If nodElement.Text = "A Good Day to Die Hard" Then ' ... get a reference to that video Set nodReference = nodElement ' Get a reference to the root node Set nodRoot = docXMLDOM.documentElement ' ... start a new node named video Set nodNewElement = docXMLDOM.createElement("video") ' Add some child nodes to the new element Set nodChild = docXMLDOM.createElement("title") nodChild.Text = "Indiana Jones and the Kingdom of the Crystal Skull" nodNewElement.appendChild nodChild Set nodChild = docXMLDOM.createElement("director") nodChild.Text = "Stephen Sielvert" nodNewElement.appendChild nodChild Set nodChild = docXMLDOM.createElement("producers") nodChild.Text = "Kathleen Kennedy, George Lucas" nodNewElement.appendChild nodChild Set nodChild = docXMLDOM.createElement("rating") nodChild.Text = "PG-13" nodNewElement.appendChild nodChild ' Add the new node before the referenced element nodRoot.replaceChild nodNewElement, nodReference.parentNode ' Save the file docXMLDOM.Save "C:\Exercises\Videos15.xml" ' Get out of the For loop (no need to look further) Exit For End If Next Set docXMLDOM = Nothing End Sub This would produce: <?xml version="1.0" encoding="utf-8" ?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
<video>
<title>Indiana Jones and the Kingdom of the Crystal Skull</title>
<director>Stephen Sielvert</director>
<producers>Kathleen Kennedy, George Lucas</producers>
<rating>PG-13</rating>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
</videos>
Now consider the following file named videos16.xml: <?xml version="1.0" encoding="utf-8" ?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
<video>
<title>Indiana Jones and the Kingdom of the Crystal Skull</title>
<director>Stephen Sielvert</director>
<producers>Kathleen Kennedy, George Lucas</producers>
<rating>PG-13</rating>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
</videos>
Imagine that the name of the director in the second video as Stephen Sielvert is wrong and you want to edit/change/update it. To do that (programmatically), you would have to replace that string. To do this, you would have to locate the name and replace/change its value. Obviously there are different approaches you can use but the whole technique (of course not the only one) is to call the IXMLDOMNodeList.replaceChild() method after locating the video. Here is one way this can be done: Private Sub cmdReplaceChild_Click() Dim docXMLDOM As DOMDocument Dim nodRoot As IXMLDOMElement Dim nodVideo As IXMLDOMElement Dim nodDirector As IXMLDOMElement Dim lstDirectors As IXMLDOMNodeList ' Initialize the document model Set docXMLDOM = New DOMDocument ' Open the XML document docXMLDOM.Load "C:\Exercises\videos16.xml" ' Get a list of nodes based on the director element Set lstDirectors = docXMLDOM.getElementsByTagName("director") ' Check the list of all nodes For Each nodVideo In lstDirectors ' If you find a video whose director is Stephen Sielvert, ... If nodVideo.Text = "Stephen Sielvert" Then ' Get a reference to the root Set nodRoot = docXMLDOM.documentElement ' Start creating a new node Set nodDirector = docXMLDOM.createElement("director") ' Specify its value nodDirector.Text = "Steven Spielberg" ' Use the new node in place of the old node nodVideo.parentNode.replaceChild nodDirector, nodVideo ' Save the file docXMLDOM.Save "C:\Exercises\Videos16.xml" ' Get out of the For loop (no need to look further) Exit For End If Next Set docXMLDOM = Nothing End Sub This would produce: <?xml version="1.0" encoding="utf-8" ?>
<videos>
<video>
<title>The Distinguished Gentleman</title>
<director>Jonathan Lynn</director>
<length>112 Minutes</length>
<format>DVD</format>
<rating>R</rating>
</video>
<video>
<title>Indiana Jones and the Kingdom of the Crystal Skull</title>
<director>Steven Spielberg</director>
<producers>Kathleen Kennedy, George Lucas</producers>
<rating>PG-13</rating>
</video>
<video>
<title>Her Alibi</title>
<director>Bruce Beresford</director>
<length>94 Minutes</length>
<format>DVD</format>
<rating>PG-13</rating>
</video>
</videos>
Using the same approach, you can edit/update/change/replace any node or child node or grand-child and/or their values. Deleting XML Elements Deleting an Element If you have a node you don't want or don't need anymore in your XML document, you can delete it. To support this operation, the IXMLDOMNode interface provides a method named removeChild. Its syntax is: Public Function removeChild(ByVal node As IXMLDOMNode) As IXMLDOMNode This method takes as argument the node to delete. If the node exists, it would be deleted and the method would return the node that was deleted. If the node does not exist, nothing would happen. To effectively use this method, you should first locate the particular node you want to delete. You can look for it using any of the logics we have applied so far. Once you find the node, you can then delete it. Consider the following file named videos17.xml: <?xml version="1.0" encoding="utf-8" ?> <videos> <video> <title>The Distinguished Gentleman</title> <director>Jonathan Lynn</director> <length>112 Minutes</length> <format>DVD</format> <rating>R</rating> </video> <video>The video is provided in Blu-ray/DVD Combo. <title>A Good Day to Die Hard</title> <director>John Moore</director> <length>98 minutes</length> </video> <video> <title>Indiana Jones and the Kingdom of the Crystal Skull</title> <director>Steven Spielberg</director> <producers>Kathleen Kennedy, George Lucas</producers> <rating>PG-13</rating> </video> <video> <title>Her Alibi</title> <director>Bruce Beresford</director> <length>94 Minutes</length> <format>DVD</format> <rating>PG-13</rating> </video> </videos> Imagine you want to delete the video titled A Good Day to Die Hard. Here is an example of calling this method to perform the operation: Private Sub cmdDeleteElement_Click() Dim docXMLDOM As DOMDocument Dim nodRoot As IXMLDOMElement Dim nodElement As IXMLDOMElement Dim lstVideos As IXMLDOMNodeList Found = False Set docXMLDOM = New DOMDocument docXMLDOM.Load "C:\Exercises\videos17.xml" Set lstVideos = docXMLDOM.getElementsByTagName("title") For Each nodElement In lstVideos If nodElement.Text = "A Good Day to Die Hard" Then Set nodRoot = docXMLDOM.documentElement nodRoot.removeChild nodElement.parentNode docXMLDOM.Save "C:\Exercises\videos17.xml" Exit For End If Next Set docXMLDOM = Nothing End Sub This would produce: <?xml version="1.0" encoding="utf-8" ?> <videos> <video> <title>The Distinguished Gentleman</title> <director>Jonathan Lynn</director> <length>112 Minutes</length> <format>DVD</format> <rating>R</rating> </video> <video> <title>Indiana Jones and the Kingdom of the Crystal Skull</title> <director>Steven Spielberg</director> <producers>Kathleen Kennedy, George Lucas</producers> <rating>PG-13</rating> </video> <video> <title>Her Alibi</title> <director>Bruce Beresford</director> <length>94 Minutes</length> <format>DVD</format> <rating>PG-13</rating> </video> </videos> Obviously, to delete the first or the last child node of an element, call either the firstChild() or the lastChild() method on the document element. Here is an example that delete the first child node of the root element: Private Sub cmdDeleteNode_Click()
Dim docXMLDOM As DOMDocument
Dim nodRoot As IXMLDOMElement
Set docXMLDOM = New DOMDocument
docXMLDOM.Load "C:\Exercises\videos17.xml"
' Get a reference to the root element
Set nodRoot = docXMLDOM.documentElement
' Delete the first child node of the root element
nodRoot.removeChild nodRoot.firstChild
docXMLDOM.Save "C:\Exercises\videos17.xml"
Set docXMLDOM = Nothing
End Sub
Deleting a Child Node of an Element Using any of these techniques, you can delete any node inside your XML document. Consider the above videos17.xml file. Imagine you want to delete a node named producers in the video titled Kathleen Kennedy, George Lucas. Here is how this can be done: Private Sub cmdDeleteChildNode_Click()
Dim docXMLDOM As DOMDocument
Dim nodProducer As IXMLDOMNode
Dim nodVideo As IXMLDOMElement
Dim lstVideos As IXMLDOMNodeList
Dim lstProducers As IXMLDOMNodeList
Set docXMLDOM = New DOMDocument
docXMLDOM.Load "C:\Exercises\videos17.xml"
' Get a list of all elements named video
Set lstVideos = docXMLDOM.getElementsByTagName("video")
' Visit each node under the root element
For Each nodVideo In lstVideos
' Create a list of all nodes named producers in the current node
Set lstProducers = nodVideo.getElementsByTagName("producers")
' Visit each producer node
For Each nodProducer In lstProducers
' Look for a producer node whose value is Kathleen Kennedy, George Lucas
If nodProducer.Text = "Kathleen Kennedy, George Lucas" Then
' Since we found such a node, delete it
nodVideo.removeChild nodProducer
' Save the updated file
docXMLDOM.Save "C:\Exercises\videos17.xml"
' Stop searching
Exit For
End If
Next
Next
Set docXMLDOM = Nothing
End Sub
This would produce: <?xml version="1.0" encoding="utf-8" ?> <videos> <video> <title>The Distinguished Gentleman</title> <director>Jonathan Lynn</director> <length>112 Minutes</length> <format>DVD</format> <rating>R</rating> </video> <video> <title>Indiana Jones and the Kingdom of the Crystal Skull</title> <director>Steven Spielberg</director> <rating>PG-13</rating> </video> <video> <title>Her Alibi</title> <director>Bruce Beresford</director> <length>94 Minutes</length> <format>DVD</format> <rating>PG-13</rating> </video> </videos> In the same way, you can delete a child of a child of a child node. |
|
||
Previous | Copyright © 2000-2022, FunctionX, Inc. | Next |
|