Solved

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

Posted on 2014-09-26
24
374 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 

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

MIM Survival Guide for Service Desk Managers

Major incidents can send mastered service desk processes into disorder. Systems and tools produce the data needed to resolve these incidents, but your challenge is getting that information to the right people fast. Check out the Survival Guide and begin bringing order to chaos.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Making Table Thru ASP Response.write 5 35
Split on ASP 8 47
Classic ASP - Display returned sql output parameter 9 50
Cross checking component service dlls 2 36
Have you ever needed to get an ASP script to wait for a while? I have, just to let something else happen. Or in my case, to allow other stuff to happen while I was murdering my MySQL database with an update. The Original Issue This was written…
Over the years I have built up my own little library of code snippets that I refer to when programming or writing a script.  Many of these have come from the web or adaptations from snippets I find on the Web.  Periodically I add to them when I come…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

739 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