Solved

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

Posted on 2014-09-26
24
369 Views
Last Modified: 2014-09-30
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..
0
Comment
Question by:mike99c
  • 15
  • 7
24 Comments
 
LVL 33

Assisted Solution

by:Big Monty
Big Monty earned 200 total points
ID: 40346369
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
 
LVL 33

Expert Comment

by:Big Monty
ID: 40346554
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
 

Author Comment

by:mike99c
ID: 40346570
OK Big Monty appreciate your input I will give this a go.
0
Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

 

Author Comment

by:mike99c
ID: 40346582
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
 

Author Comment

by:mike99c
ID: 40346831
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
 
LVL 33

Expert Comment

by:Big Monty
ID: 40346867
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
 

Author Comment

by:mike99c
ID: 40346891
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
 
LVL 33

Expert Comment

by:Big Monty
ID: 40346896
when you're looping through the nodes, check the TEXT property of next node, if it is blank, it has no child nodes
0
 

Author Comment

by:mike99c
ID: 40346900
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
 
LVL 33

Expert Comment

by:Big Monty
ID: 40347181
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
 

Author Comment

by:mike99c
ID: 40347507
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
 

Author Comment

by:mike99c
ID: 40347528
Oops my mistake, forgot to add "Set".
0
 

Author Comment

by:mike99c
ID: 40347556
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
 

Author Comment

by:mike99c
ID: 40347567
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
 
LVL 33

Expert Comment

by:Big Monty
ID: 40347584
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
 

Author Comment

by:mike99c
ID: 40347608
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
 

Author Comment

by:mike99c
ID: 40347615
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
 

Author Comment

by:mike99c
ID: 40349432
Any takers? Will give it another hour before I close this down.
0
 
LVL 35

Accepted Solution

by:
Robert Schutt earned 300 total points
ID: 40350047
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
 

Author Comment

by:mike99c
ID: 40350161
The check to see if a tag contains nested tags is achieved using:

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

OR

hasChildElements(i)
0
 
LVL 33

Expert Comment

by:Big Monty
ID: 40350166
why no split? i got you the majority of the way there I thought
0
 

Author Comment

by:mike99c
ID: 40350309
Hi Big Monty, Apologies for this, I have asked Experts Exchange to reset the points awarded so I can award a split.
0
 

Author Comment

by:mike99c
ID: 40351746
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

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Nobody understands Phishing better than an anti-spam company. That’s why we are providing Phishing Awareness Training to our customers. According to a report by Verizon, only 3% of targeted users report malicious emails to management. With compan…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question