Problems with iteration of IXMLDOMNodeList

M

Martin Danielson

I have a problem that I can't work out. I have a script in ASP using VBScript that act quite funny when editing and xml file. Here is my explenation

I have the following xml-fil

<root><element type="type1">element 1</element><element type="type1">element 2</element><element type="type1">element 3</element><element type="type2">element 4</element><element type="type2">element 5</element></root

I wanted to order them by type, by creating a new node for each type in the root element and then inserting the corresponding elements into the type node. The output should be looking like this

<root><type1><element type="type1">element 1</element><element type="type1">element 2</element><element type="type1">element 3</element></type1><type2><element type="type2">element 4</element><element type="type2">element 5</element></type2></root

Now, when doing this I first got all the element nodes into an IXMLDOMNodeList, I used the method .getElementsByTagName( "element" ). No problem there. Since I don't like to use "For X = 0 To Y" I used "For Each X In Y" instead, where Y was the IXMLDOMNodeList
Then, within the loop i took the current Nodes parent and appended a child to it with the type as the nodeName, if the type was different from the last nodes type. Then I kept adding current node to the nodes parents last child, which resulted in me moving the elements into the correct type node

When doing this the first time i printed the length of the IXMLDOMNodeList at the beginning of the file, but when i removed it everything went crazy. It seems that when I dodn't check the length (either by responsing it or just by setting a "dumb" variable to it) the loop went on forever. I read that the IXMLDOMNodeList was live and that got me thinking that for each loop the referense to .getElementsByTagName was run and it would keep finding new ones. But that still dowesn't explain why it worked when geting the length of it first hand. I later on tried the "For X = 0 To IXMLDOMNodeList.length -1" approach and that worked fine since i called upon the length property
Then I got back to the "For Each X In Y" code and added a exact copy of the enumeration before the orgininal one, without doing anything, and that seemed to "lock" the length and worked fine. This got me really confused

The last thing I tried was to use the selectNodes method where i specifically got the "/root/element" nodes and that turned out great. When using "//element" as the XPath the script acted as when I use the .getElementsByTagName approach. I stuck with this just to get moving but I am still not up to speed what was going on. Is this a bug or is it supposed to re-run the search every iteration when using "For Each X In Y"

Please, put me at ease and explain this to me. I used DOMDocument.3.0

Many thanks in advance
Martin Danielson
 
B

Bob Barrows

Martin said:
I have a problem that I can't work out. I have a script in ASP using
VBScript that act quite funny when editing and xml file. Here is my
explenation:

I have the following xml-file

<root><element type="type1">element 1</element><element
type="type1">element 2</element><element type="type1">element
3</element><element type="type2">element 4</element><element
type="type2">element 5</element></root>

I wanted to order them by type, by creating a new node for each type
in the root element and then inserting the corresponding elements
into the type node.

Well, you are doing it the hard way. Here is a function (actually, two
functions) from my code library that I wrote for re-ordering an xml
document. See if you can adapt it to your needs:

function SortXMLdocBySingleElement(pxmlDoc,psEl, _
psType, psDirection)
'****************************************************
'Pass an xml document, an element name, a datatype name
'(Integer, String, Long, Double, Single, or Date) and a direction
'(ASC or DESC). Usage example:
' set xmldoc=SortXMLdocBySingleElement(xmldoc, _
' "MyElement","String","ASC")
'****************************************************
dim i, j,lChildNodes, vCurVal, vNewVal, oRoot
dim oReplacedNode, oNode, oNewNode
dim xmldoc
set xmldoc = pxmldoc
set oRoot = xmldoc.documentelement
lChildNodes=oRoot.childnodes.length

for i = 0 to lChildNodes - 2
set oNode = oRoot.childnodes(i)
vCurVal = ConvertToSpecifiedType(oNode.selectsinglenode(psEl).text,psType)
for j = i + 1 to lChildNodes - 1
set oNewNode = oRoot.childnodes(j)
vNewVal =
ConvertToSpecifiedType(oNewNode.selectsinglenode(psEl).text,psType)
if psDirection = "ASC" Then
if vNewVal < vCurVal then
set oReplacedNode =
oRoot.insertbefore(oRoot.childnodes(j),oRoot.childnodes(i))
vCurVal = vNewVal
end if
else
if vNewVal > vCurVal then
set oReplacedNode =
oRoot.insertbefore(oRoot.childnodes(j),oRoot.childnodes(i))
vCurVal = vNewVal
end if
end if
next
next
Set SortXMLdocBySingleElement = xmldoc
end function

function ConvertToSpecifiedType(pvData,psType)
Select Case psType
case "Integer": ConvertToSpecifiedType = CInt(pvData)
case "String": ConvertToSpecifiedType = CStr(pvData)
case "Long": ConvertToSpecifiedType = CLng(pvData)
case "Double": ConvertToSpecifiedType = CDbl(pvData)
case "Single": ConvertToSpecifiedType = CSng(pvData)
case "Date": ConvertToSpecifiedType = CDate(pvData)
end select
end function


There are also techniques using xsl transformations that can make short work
of this. A Google search should turn up some examples.

HTH,
Bob Barrows
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,144
Messages
2,570,823
Members
47,369
Latest member
FTMZ

Latest Threads

Top