ASP classic script needed to read every single tag value and attribute

I am using ASP classic with VBScript and would like to read all tag names, attributes and values of an XML file.

I have the following code example which I have started and would like a simple script to output everything starting from the <result> tag and everything within it.

Dim xmlstr, xmlObj, xmlList, xmlItem, Row, Details, detail

	xmlstr= "<?xml version=""1.0"" encoding=""UTF-8"" ?>" &_
			"<response uri=""/crm/private/xml/Leads/insertRecords"">" &_
			"  <result>" &_
			"	<row no=""3"">" &_
			"	  <success>" &_
			"       <code>2000</code>" &_
			"		<details>" &_
			"		  <FL val=""Id"">1240444000000100001</FL>" &_
			"		  <FL val=""Created Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Modified Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Created By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		  <FL val=""Modified By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		</details>" &_
			"	  </success>" &_
			"	</row>" &_
			"	<row no=""2"">" &_
			"	  <success>" &_
			"       <code>2000</code>" &_
			"		<details>" &_
			"		  <FL val=""Id"">1240444000000100002</FL>" &_
			"		  <FL val=""Created Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Modified Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Created By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		  <FL val=""Modified By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		</details>" &_
			"	  </success>" &_
			"	</row>" &_
			"	<row no=""1"">" &_
			"	  <success>" &_
			"       <code>2000</code>" &_
			"		<details>" &_
			"		  <FL val=""Id"">1240444000000100003</FL>" &_
			"		  <FL val=""Created Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Modified Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Created By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		  <FL val=""Modified By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		</details>" &_
			"	  </success>" &_
			"	</row>" &_
			"  </result>" &_
			"</response>"

	Set xmlObj = Server.CreateObject("Microsoft.XMLDOM")
	xmlObj.async = False
	xmlObj.setProperty "ServerHTTPRequest", True
	xmlObj.LoadXML(xmlstr)
	If xmlObj.parseError.errorCode <> 0 Then
		'### NOTHING
	End If
	
	Set xmlList = xmlObj.getElementsByTagName("result")
	
	' Scan through result tags but in this case there is only one
	For Each xmlItem In xmlList  
	
               ' What do I do now?
		
	Next
			
	Set xmlList = Nothing
	Set xmlObj = Nothing

Open in new window


So what I am looking for is an output like this:

row - no:1
   success
      code = 2000
      details
           FL - val:Id = 1240444000000100001
           FL - val:Created Time = 1240444000000100001

"
"
row - no:2
   success
      code = 2000
      details
           FL - val:Id = 1240444000000100002
           FL - val:Created Time = 2014-09-26 00:47:16

Etc..
mike99cAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
have a look at this tutorial, it'll show you how to loop through everything.

http://www.w3schools.com/dom/dom_nodes_access.asp

gimme a few minutes to come up with an example using your code
0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
sorry, something came up that's going to require my attention for the rest of the day. Didn't want to leave you hanging, so here's something that'll get cyou a reference to each row. hopefully someone else comes along and can help finish up whatever questions you may have, otherwise I'll try to get to this later

add the following code to the section where you want to loop through the xml doc and parse everything out

Set itemList = xmlObj.SelectNodes("response/result")
 
For Each itemAttrib In itemList
    '   Response.Write itemAttrib.SelectNodes("response/result").getAttribute("row").text
       Response.Write itemAttrib.SelectSingleNode("row").text

Next

Open in new window

0
mike99cAuthor Commented:
OK Big Monty appreciate your input I will give this a go.
0
Fundamentals of JavaScript

Learn the fundamentals of the popular programming language JavaScript so that you can explore the realm of web development.

mike99cAuthor Commented:
I tried inserting the script and got the following output:
2000 1240444000000100001 2014-09-26 00:47:16 2014-09-26 00:47:16 John Smith John Smith

It seems to only output all the child tag values in the first row tag only. I had similar issues before and need to get all the other values too.
0
mike99cAuthor Commented:
OK I have made some progress and managed to list the tags, values and attributes using the following code:

	Dim x, y, z, i, j
	For Each x in xmlObj.documentElement.childNodes
	
	    response.write x.nodename & "<br>"
		
		For Each y in x.childNodes

	        response.write " -- " & y.nodename & " no: " & y.GetAttribute("no") & " hasChildNodes: " & y.hasChildNodes & "<br>"

			For Each z in y.childNodes
	
				response.write " ---- " & z.nodename & " hasChildNodes: " & y.hasChildNodes & "<br>"

				For Each i in z.childNodes
		
					response.write " ------ " & i.nodename & " " & i.text & " hasChildNodes: " & i.hasChildNodes & "<br>"
					
					If i.nodename = "details" Then

						For Each j in i.childNodes
				
							response.write " -------- " & j.nodename & " - " & j.text  & " val: " & j.GetAttribute("val") & " hasChildNodes: " & j.hasChildNodes & "<br>"
						
						Next
					
					End if
				
				Next
			
			Next
		
		Next
		
	Next

Open in new window


The output is as follows:

result
-- row no: 3 hasChildNodes: True
---- success hasChildNodes: True
------ code 2000 hasChildNodes: True
------ details 1240444000000100001 2014-09-26 00:47:16 2014-09-26 00:47:16 John Smith John Smith hasChildNodes: True
-------- FL - 1240444000000100001 val: Id hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Created Time hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Modified Time hasChildNodes: True
-------- FL - John Smith val: Created By hasChildNodes: True
-------- FL - John Smith val: Modified By hasChildNodes: True
-- row no: 2 hasChildNodes: True
---- success hasChildNodes: True
------ code 2000 hasChildNodes: True
------ details 1240444000000100002 2014-09-26 00:47:16 2014-09-26 00:47:16 John Smith John Smith hasChildNodes: True
-------- FL - 1240444000000100002 val: Id hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Created Time hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Modified Time hasChildNodes: True
-------- FL - John Smith val: Created By hasChildNodes: True
-------- FL - John Smith val: Modified By hasChildNodes: True
-- row no: 1 hasChildNodes: True
---- success hasChildNodes: True
------ code 2000 hasChildNodes: True
------ details 1240444000000100003 2014-09-26 00:47:16 2014-09-26 00:47:16 John Smith John Smith hasChildNodes: True
-------- FL - 1240444000000100003 val: Id hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Created Time hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Modified Time hasChildNodes: True
-------- FL - John Smith val: Created By hasChildNodes: True
-------- FL - John Smith val: Modified By hasChildNodes: True

Open in new window


Now rather than close this task I would like help with something which I am confused about. I have called the property hasChildNodes and I was hoping this would return False if a tag does not contain anymore children. For example the <code> tag returns True for hasChildNodes but I was expecting it to return False. The same applies for the tag <FL>, surely this should also return False.

Among other things I do not for example want to output the text for tag <details> as it contains children.
0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
the hasChildNodes property is a bit mis-leading, as it'll only return false if no text is present in the node, as any text that IS present is considered a separate node.

http://www.w3schools.com/dom/dom_nodes.asp

try taking out any of the text in between the FL tags, and you'll see the hasChildNodes property return false.
0
mike99cAuthor Commented:
OK thanks, so how do I make the test work like I want? That is I need a test to check if a tag contains child tags hence:

<code>200</code>
Should return false

<details>
  <FL ..
</details>
Should return true.
0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
when you're looping through the nodes, check the TEXT property of next node, if it is blank, it has no child nodes
0
mike99cAuthor Commented:
Unfortunately that does not work because when I output the text property for the tag <details> I get:

1240444000000100001 2014-09-26 00:47:16 2014-09-26 00:47:16 John Smith John Smith

The text property seems to return the values of all the child tags.
0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
Have a look at the link below, it makes use of the NOTHING keyword

http://forums.devx.com/showthread.php?3020-Quick-way-to-check-if-an-element-exists
0
mike99cAuthor Commented:
Thanks Big Monty, however I am having problems assigning the node and get a run time error.

Here is the modified code:

	Set xmlObj = Server.CreateObject("Microsoft.XMLDOM")
	xmlObj.async = False
	xmlObj.setProperty "ServerHTTPRequest", True
	xmlObj.LoadXML(xmlstr)
	If xmlObj.parseError.errorCode <> 0 Then
		'### NOTHING
	End If
	
	Dim x, y, z, i, j, node
	For Each x in xmlObj.documentElement.childNodes
	
	    response.write x.nodename & "<br>"
		
		For Each y in x.childNodes

	        response.write " -- " & y.nodename & " no: " & y.GetAttribute("no") & " hasChildNodes: " & y.hasChildNodes() & "<br>"

			For Each z in y.childNodes
	
				response.write " ---- " & z.nodename & " hasChildNodes: " & y.hasChildNodes() & "<br>"

				For Each i in z.childNodes
		
					response.write " ------ " & i.nodename & " " & i.text & " hasChildNodes: " & i.hasChildNodes() & "<br>"
					
					node = xmlObj.selectSingleNode(i.nodename)
					
					If i.nodename = "details" Then

						For Each j in i.childNodes
				
							response.write " -------- " & j.nodename & " - " & j.text  & " val: " & j.GetAttribute("val") & " hasChildNodes: " & j.hasChildNodes() & "<br>"
						
						Next
					
					End if
				
				Next
			
			Next
		
		Next
		
	Next

Open in new window


Before I can do the check I added the following line:
node = xmlObj.selectSingleNode(i.nodename)

However i get  the following run time error:
Microsoft VBScript runtime error '800a005b'

Object variable not set
0
mike99cAuthor Commented:
Oops my mistake, forgot to add "Set".
0
mike99cAuthor Commented:
Ok I tried:
Set node = xmlObj.selectSingleNode(i.nodename)

I can confirm that this returns "nothing" for both < code> and <description>. I am quite amazed how difficult it is to identify something so simple.

Going to try getElementsbyTagName and look at the length as described in http://forums.devx.com/showthread.php?3020-Quick-way-to-check-if-an-element-exists.
0
mike99cAuthor Commented:
Ok I tried the following:

Set nodes = xmlObj.selectNodes(i.nodename)
response.write " ------ " & i.nodename & " length: " & nodes.length & "<br>"

Open in new window


Unfortunately a length of zero is returned for tags <code> and <details>. Surely there must be a simple solution to this.
0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
Can you post the latest version of your code, including the xml, and I'll have a look tonight if I get a chance? You're right, it shouldn't be this difficult :)
0
mike99cAuthor Commented:
Ok here is the complete script in which I check single node, node length and first child and I cannot differentiate anything between a tag containing just data and one containing child tags.

Here is the full code:

Dim xmlstr, xmlObj, xmlList, x, y, z, i, j, node, nodes, fc

	xmlstr= "<?xml version=""1.0"" encoding=""UTF-8"" ?>" &_
			"<response uri=""/crm/private/xml/Leads/insertRecords"">" &_
			"  <result>" &_
			"	<row no=""3"">" &_
			"	  <success>" &_
			"       <code>2000</code>" &_
			"		<details>" &_
			"		  <FL val=""Id"">1240444000000100001</FL>" &_
			"		  <FL val=""Created Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Modified Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Created By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		  <FL val=""Modified By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		</details>" &_
			"	  </success>" &_
			"	</row>" &_
			"	<row no=""2"">" &_
			"	  <success>" &_
			"       <code>2000</code>" &_
			"		<details>" &_
			"		  <FL val=""Id"">1240444000000100002</FL>" &_
			"		  <FL val=""Created Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Modified Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Created By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		  <FL val=""Modified By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		</details>" &_
			"	  </success>" &_
			"	</row>" &_
			"	<row no=""1"">" &_
			"	  <success>" &_
			"       <code>2000</code>" &_
			"		<details>" &_
			"		  <FL val=""Id"">1240444000000100003</FL>" &_
			"		  <FL val=""Created Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Modified Time"">2014-09-26 00:47:16</FL>" &_
			"		  <FL val=""Created By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		  <FL val=""Modified By"">" &_
			"			<![CDATA[John Smith]]>" &_
			"		  </FL>" &_
			"		</details>" &_
			"	  </success>" &_
			"	</row>" &_
			"  </result>" &_
			"</response>"

	Set xmlObj = Server.CreateObject("Microsoft.XMLDOM")
	xmlObj.async = False
	xmlObj.setProperty "ServerHTTPRequest", True
	xmlObj.LoadXML(xmlstr)
	If xmlObj.parseError.errorCode <> 0 Then
		'### NOTHING
	End If
	
	For Each x in xmlObj.documentElement.childNodes
	
	    response.write x.nodename & "<br>"
		
		For Each y in x.childNodes

	        response.write " -- " & y.nodename & " no: " & y.GetAttribute("no") & " hasChildNodes: " & y.hasChildNodes() & "<br>"

			For Each z in y.childNodes
	
				response.write " ---- " & z.nodename & " hasChildNodes: " & y.hasChildNodes() & "<br>"

				For Each i in z.childNodes
		
					response.write " ------ " & i.nodename & " " & i.text & " hasChildNodes: " & i.hasChildNodes() & " nodeType: " & i.nodeType &  "<br>"
					
					Set node = xmlObj.selectSingleNode(i.nodename)
					If node is Nothing Then
					   response.write " ------ " & i.nodename & " is nothing<br>"
					Else
					   response.write " ------ " & i.nodename & " is NOT nothing<br>"
					End If
										
					Set nodes = xmlObj.selectNodes(i.nodename)
					response.write " ------ " & i.nodename & " length: " & nodes.length & "<br>"
					
					Set fc = xmlObj.documentElement.firstChild
					response.write " ------ " & i.nodename & " fc.nodeType: " & fc.nodeType & "<br>"
					
					If i.nodename = "details" Then

						For Each j in i.childNodes
				
							response.write " -------- " & j.nodename & " - " & j.text  & " val: " & j.GetAttribute("val") & " hasChildNodes: " & j.hasChildNodes() & "<br>"
						
						Next
					
					End if
				
				Next
			
			Next
		
		Next
		
	Next
	
	Set xmlList = Nothing
	Set xmlObj = Nothing

Open in new window


And here is the output:

result
-- row no: 3 hasChildNodes: True
---- success hasChildNodes: True
------ code 2000 hasChildNodes: True nodeType: 1
------ code is nothing
------ code length: 0
------ code fc.nodeType: 1
------ details 1240444000000100001 2014-09-26 00:47:16 2014-09-26 00:47:16 John Smith John Smith hasChildNodes: True nodeType: 1
------ details is nothing
------ details length: 0
------ details fc.nodeType: 1
-------- FL - 1240444000000100001 val: Id hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Created Time hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Modified Time hasChildNodes: True
-------- FL - John Smith val: Created By hasChildNodes: True
-------- FL - John Smith val: Modified By hasChildNodes: True
-- row no: 2 hasChildNodes: True
---- success hasChildNodes: True
------ code 2000 hasChildNodes: True nodeType: 1
------ code is nothing
------ code length: 0
------ code fc.nodeType: 1
------ details 1240444000000100002 2014-09-26 00:47:16 2014-09-26 00:47:16 John Smith John Smith hasChildNodes: True nodeType: 1
------ details is nothing
------ details length: 0
------ details fc.nodeType: 1
-------- FL - 1240444000000100002 val: Id hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Created Time hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Modified Time hasChildNodes: True
-------- FL - John Smith val: Created By hasChildNodes: True
-------- FL - John Smith val: Modified By hasChildNodes: True
-- row no: 1 hasChildNodes: True
---- success hasChildNodes: True
------ code 2000 hasChildNodes: True nodeType: 1
------ code is nothing
------ code length: 0
------ code fc.nodeType: 1
------ details 1240444000000100003 2014-09-26 00:47:16 2014-09-26 00:47:16 John Smith John Smith hasChildNodes: True nodeType: 1
------ details is nothing
------ details length: 0
------ details fc.nodeType: 1
-------- FL - 1240444000000100003 val: Id hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Created Time hasChildNodes: True
-------- FL - 2014-09-26 00:47:16 val: Modified Time hasChildNodes: True
-------- FL - John Smith val: Created By hasChildNodes: True
-------- FL - John Smith val: Modified By hasChildNodes: True

Open in new window

0
mike99cAuthor Commented:
I think the first child may help but the following may not be correct:

Set fc = xmlObj.documentElement.firstChild

Instead of xmlObj I need to take it from the current node. I tried:

Set fc = i.documentElement.firstChild
Set fc = z.childNodes.documentElement.firstChild
Set fc = z.childNodes.firstChild

And all these flag errors.

Set fc = xmlObj.documentElement.firstChild
response.write " ------ " & i.nodename & " fc.nodeType: " & fc.nodeType & "<br>"
response.write " ------ " & i.nodename & " fc.text: " & fc.text & "<br>"
response.write " ------ " & i.nodename & " fc.tagName: " & fc.tagName & "<br>"

Open in new window


I know Set fc = xmlObj.documentElement.firstChild is not right because the tagName returned is result which is the top level tag.
0
mike99cAuthor Commented:
Any takers? Will give it another hour before I close this down.
0
Robert SchuttSoftware EngineerCommented:
I'm actually not really sure what your current issues are but I'll pick one out: as BigMonty explained, properties and methods of the XML Node class like childNodes, hasChildNodes() and firstChild also pertain to text nodes. If you want to determine whether a node has child elements (or child tags as you called it here) then you will need to check the node type of each of the childNodes for example with a function like this:
Function hasChildElements(n)
	Dim subnode
	For Each subnode In n.childNodes
		If subnode.nodeType = 1 Then ' Element
			hasChildElements = True
			Exit Function
		End If
	Next
	hasChildElements = False
End Function

Open in new window

Using that in your code for example:
response.write " ------ " & i.nodename & " " & i.text & " hasChildNodes: " & i.hasChildNodes() & " <b>hasChildElements: " & hasChildElements(i) & "</b> nodeType: " & i.nodeType &  "<br>"

Open in new window

In the output you will now see sometimes i.hasChildNodes being true while hasChildElements(i) is false, which means in your situation there is only text in the node (for example <code>).

Now it's not clear to me what you want next but you can use that function in an "if" statement and decide how to process further depending on this information. Or, maybe simpler, you can check for nodeType = 1 in the For Each loops.

Or, changing a bit of code you already have in there: you can search for any child element of the current node i with:
					Set node = i.selectSingleNode(".//*")
					If node is Nothing Then
					   response.write " ------ " & i.nodename & " 'any child element' is nothing<br>"
					Else
					   response.write " ------ " & i.nodename & " 'any child element' is NOT nothing<br>"
					End If

Open in new window

In the following output you can see these code changes give consistent results: where hasChildElements() returns false, the 'any child element' is nothing (for example <code>) and where hasChildElements() is true, the 'any child element' is NOT nothing (for example <details>). So you can use either of these methods.
...
-- row no: 1 hasChildNodes: True
---- success hasChildNodes: True
------ code 2000 hasChildNodes: True hasChildElements: False nodeType: 1
------ code 'any child element' is nothing
------ details 1240444000000100003 2014-09-26 00:47:16 2014-09-26 00:47:16 John Smith John Smith hasChildNodes: True hasChildElements: True nodeType: 1
------ details 'any child element' is NOT nothing
...

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mike99cAuthor Commented:
The check to see if a tag contains nested tags is achieved using:

Set node = i.selectSingleNode(".//*")

OR

hasChildElements(i)
0
Big MontySenior Web Developer / CEO of ExchangeTree.org Commented:
why no split? i got you the majority of the way there I thought
0
mike99cAuthor Commented:
Hi Big Monty, Apologies for this, I have asked Experts Exchange to reset the points awarded so I can award a split.
0
mike99cAuthor Commented:
Thanks Robert. I know how to split points and have done so many times, it's just that on this occassion I should have split it with Big Monty.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP

From novice to tech pro — start learning today.