הערה
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות להיכנס או לשנות מדריכי כתובות.
הגישה לדף זה מחייבת הרשאה. באפשרותך לנסות לשנות מדריכי כתובות.
Question
Wednesday, July 1, 2015 7:45 AM
Hi - I have got stuck trying to see if an XML node exists in Visual Basic 2010 without causing an error.
Here is the file I am dealing with:
<?xml version="1.0"?>
<HamQTH version="2.6" xmlns="http://www.hamqth.com">
<session>
<error>Wrong user name or password</error>
</session>
</HamQTH>
and I want to see if the 'error' tag-pair exists. I have tried:
hamqthDoc.Load(hamqthStream)
nodes = hamqthDoc.SelectNodes("HamQTH/session")
Dim errorNode As System.Xml.XmlNode = nodes.Item(0).SelectSingleNode("error")
If errorNode IsNot Nothing Then...
If nodes.Item(0).SelectSingleNode("error") IsNot Nothing Then..
If Not IsNothing(nodes.Item(0).SelectSingleNode("error")) Then...
and they all cause:
NullReferenceException was unhandled: Object reference not set to an instance of an object.
After an hour of Googling, I still have not found any code that works.
Short of catching the error in an error-handler, what is the correct way to do this in VB2010, please?
All replies (13)
Wednesday, July 1, 2015 10:15 AM ✅Answered | 1 vote
Here is another way:
Dim xe As XElement
xe = XElement.Load("pathname to file or URI here")
For Each el As XElement In xe.Descendants
If el.Name.LocalName = "session" Then
For Each els As XElement In el.Descendants
If els.Name.LocalName = "error" Then
Stop
End If
Next
End If
Next
'Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it.' JohnWein
Multics
My Serial Port Answer
Wednesday, July 1, 2015 8:54 AM | 1 vote
I would use something like
Dim hamqthdoc As XDocument
Dim eElements As List(Of XElement)
hamqthdoc = XDocument.Load("YourXmlFileLocation")
eElements = (From elements In hamqthdoc.Descendants
Where (elements.Name.LocalName.ToString() = "session")
Select elements).ToList()
For Each z As XElement In eElements
MessageBox.Show(z.Value)
Next
Wednesday, July 1, 2015 9:48 AM
XmlDocument.GetElementsByTagName Method
This just gets the first element item with the tag name of "error" (index 0). If there were more items with that tag name then I suppose you could use a loop to get all of them altering the code a bit I believe.
Option Strict On
Imports System.Xml
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
Label1.Text = "Waiting"
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim doc As New XmlDocument()
doc.LoadXml(My.Computer.FileSystem.ReadAllText("C:\Users\John\Desktop\HamQTH.Xml"))
Dim root As XmlElement = doc.DocumentElement
Label1.Text = root.GetElementsByTagName("error").Item(0).InnerText
End Sub
End Class
La vida loca
Wednesday, July 1, 2015 10:03 AM
Hi Rbie - Thanks for your answer, but that just gives an error 'Root Element is Missing'.
Surely there is just a way to simply tell if an XML tag is there or not? I can simulate this working by manually entering the strings sent from a browser, so I know the server is outputting the code and my example has a chance of working. Here is the full code of this example:
Dim hamqthUrl = "http://www.hamqth.com/xml.php?"
Dim hamqthRequest As System.Net.WebRequest
Dim hamqthResponse As System.Net.WebResponse
Dim hamqthStream As System.IO.Stream
Dim hamqthDoc As New System.Xml.XmlDocument
Dim nodes As System.Xml.XmlNodeList
hamqthRequest = System.Net.WebRequest.Create(hamqthUrl & "u=" & hamqthUser & "&p=" & hamqthPass)
hamqthResponse = hamqthRequest.GetResponse()
hamqthStream = hamqthResponse.GetResponseStream()
hamqthDoc.Load(hamqthStream)
nodes = hamqthDoc.SelectNodes("HamQTH/session")
So, within the <session> tag-pair, there will be returned EITHER <session_id>value</session_id> OR <error>value</error>. What I need to do is to see which is returned, and then get the value of the one that is returned.
Wednesday, July 1, 2015 10:39 AM
I suppose this works but I don't particularly care for it since there's probably a method to determine if either "error" or "session_id" exists without using Try/Catch to avoid errors.
Option Strict On
Imports System.Xml
Imports System.Net
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2)))
Label1.Text = "Waiting"
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim request As WebRequest = WebRequest.Create("http://www.hamqth.com/xml.php?")
request.Credentials = CredentialCache.DefaultCredentials
Using response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)
Console.WriteLine(response.StatusDescription)
Using dataStream As IO.Stream = response.GetResponseStream()
Using reader As New IO.StreamReader(dataStream)
Dim responseFromServer As String = reader.ReadToEnd()
Dim doc As New XmlDocument()
doc.LoadXml(responseFromServer)
Dim root As XmlElement = doc.DocumentElement
Try
Label1.Text = root.GetElementsByTagName("error").Item(0).InnerText
Catch ex As Exception
End Try
Try
Label1.Text = root.GetElementsByTagName("session_id").Item(0).InnerText
Catch ex As Exception
End Try
End Using
End Using
End Using
End Sub
End Class
Xml displayed on WebSite in I.E.
La vida loca
Wednesday, July 1, 2015 11:07 AM
Weird, I can read the file you posted without any problem, So my guess is you didn't use my exact code or the actual xml file is different from what you posted. This is the result I get
Wednesday, July 1, 2015 11:35 AM
Since the problem is caused by the namespace, try this variant too:
Dim m = New XmlNamespaceManager(hamqthDoc.NameTable)
m.AddNamespace("ns", "http://www.hamqth.com")
Dim error_node = hamqthDoc.SelectSingleNode("/*/ns:session/ns:error", m)
If error_node IsNot Nothing Then
' the <error> node exists
Dim text = error_node.InnerText.Trim
...
End If
Wednesday, July 1, 2015 11:36 AM
Hi Multics - thanks, I got my code working using your example. In my xml, there will either be a <session_id>value</session_id> or a <error>value</error> tag contained within the <session> tag-pair, so I was able to do some logic that looked for the value of first one, and then the other.
However for future knowledge, it would still be nice to know how to check if a tag isn't there, without causing an error. Using your loop, I could, of course, wait until the end of the loop and see if a particular tag-name had been encountered. If no one else comes up with something better, that will have to do.
Wednesday, July 1, 2015 11:40 AM
Yes sir, 'Try' would be another way to do it, but I really didn't want to go down that route, as I am already using Try in a larger loop that this code is a part of. Thanks, anyway for taking the time to add your suggestion.
Wednesday, July 1, 2015 2:39 PM | 1 vote
Tim,
You have lots of answers here - I'll add in my suggestion also for what it's worth:
Option Strict On
Option Explicit On
Option Infer Off
Imports System.IO.Path
Imports <xmlns:ns="http://www.hamqth.com">
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
Dim desktop As String = _
My.Computer.FileSystem.SpecialDirectories.Desktop
Dim xPath As String = Combine(desktop, "Example.xml")
Dim result As Boolean = CheckIfTagExist(xPath)
Stop
End Sub
Private Function CheckIfTagExist(ByVal filePath As String) As Boolean
Dim retVal As Boolean = False
If My.Computer.FileSystem.FileExists(filePath) Then
Dim xDoc As XElement = XElement.Load(filePath)
Dim errorTag As XElement = xDoc...<ns:error>.FirstOrDefault
If errorTag IsNot Nothing Then
retVal = True
End If
End If
Return retVal
End Function
End Class
Still lost in code, just at a little higher level.
:-)
Thursday, July 2, 2015 11:18 AM
You are correct - my silly mistake - I had an extra line of code in the processing which stopped your code from working.
Thursday, July 2, 2015 11:40 AM
For some reason yesterday I couldn't see that there was a namespace. Here is an example based on what Frank posted. Franks example will work, assuming that he has used the correct namespace, but it can fail if <error> occurs outside of <session>.
'simulated file
Dim xe As XElement = <HamQTH version="2.6">
<error>nit is seesion Wrong user name or password</error>
<session>
<error>Wrong user name or password</error>
</session>
</HamQTH>
'xe = XElement.Load("path or uri") 'read file or uri
'references to elements will need namespaces of the actual XML added
Dim errorTag As XElement = xe...<error>.FirstOrDefault
Stop 'examine errorTag
errorTag = xe...<session>...<error>.FirstOrDefault
If errorTag IsNot Nothing Then
Stop
End If
'Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it.' JohnWein
Multics
My Serial Port Answer
Thursday, July 2, 2015 1:26 PM
... but it can fail if <error> occurs outside of <session>.
Well yes, I did make the assumption that what he showed is from what he wanted to use it for. ;-)
Still lost in code, just at a little higher level.
:-)