-
Jan 11th, 2022, 12:00 AM
#1
Thread Starter
Lively Member
Navigating an XML structure - please help
I am writing what should be a simple Visual Basic program, but I am having trouble navigating an XML structure. In my code, I have some lines that retrieve XML from a website in the form of a string (responseBody), which I then dumped to a file – and when the file is dragged into a browser window, the XML looks fine. Here is a portion of that XML:
<?xml version="1.0" encoding="UTF-8"?>
<weatherdata><location><name>Saline</name><type></type><country>US</country><timezone>-18000</timezone><location altitude="0" latitude="42.1698" longitude="-83.7849" geobase="geonames" geobaseid="0"></location></location><credit></credit><meta><lastupdate></lastupdate><calctime>0</calctime><nextupdate></nextupdate></meta><sun rise="2022-01-10T13:02:51" set="2022-01-10T22:22:06"></sun><forecast><time from="2022-01-11T03:00:00" to="2022-01-11T06:00:00"><symbol number="803" name="broken clouds" var="04n"></symbol><precipitation probability="0"></precipitation><windDirection deg="304" code="NW" name="Northwest"></windDirection><windSpeed mps="3.86" unit="m/s" name="Gentle Breeze"></windSpeed><windGust gust="7.49" unit="m/s"></windGust><temperature unit="kelvin" value="260.06" min="260.06" max="260.14"></temperature><feels_like value="253.06" unit="kelvin"></feels_like><pressure unit="hPa" value="1035"></pressure><humidity value="71" unit="%"></humidity><clouds value="broken clouds" all="66" unit="%"></clouds><visibility value="10000"></visibility></time><time from="2022-01-11T06:00:00" to="2022-01-11T09:00:00"><symbol number="802" name="scattered clouds" var="03n"></symbol><precipitation probability="0"></precipitation><windDirection deg="291" code="WNW" name="West-northwest"></windDirection><windSpeed mps="2.27" unit="m/s" name="Light breeze"></windSpeed><windGust gust="3.81" unit="m/s"></windGust><temperature unit="kelvin" value="260.25" min="260.25" max="260.37"></temperature><feels_like value="255.21" unit="kelvin"></feels_like><pressure unit="hPa" value="1035"></pressure><humidity value="74" unit="%"></humidity><clouds value="scattered clouds" all="29" unit="%"></clouds><visibility value="10000"></visibility></time></forecast></weatherdata>
What I would like to do is simply this: Access the max temperature for the date/time 2022-01-11 @ 4:00 (which is within the times listed in the first <time> element). Would you please show me how to do this? I have tried:
Code:
Dim xd As New XmlDocument()
xd.Load(New StringReader(responseBody))
Dim nav As XPathNavigator = xd.CreateNavigator()
but was not able to figure out how to get into the structure.
-
Jan 11th, 2022, 03:54 AM
#2
Addicted Member
Re: Navigating an XML structure - please help
First off I don't really use VB much these days but this should do what you are asking. There are a few ways you can go about doing this, but I will show with xpath. Here is a simple console example.
Code:
Imports System.Xml
Imports System.Xml.XPath
Module WeatherReader
Sub Main()
Dim found As Boolean = False
Dim MyDate As DateTime = DateTime.ParseExact("2022-01-11 04:00", "yyyy-MM-dd HH:mm", Nothing)
Dim sFrom, sTo As String
Dim fDate, tDate As Date
Dim doc As New XmlDocument
doc.Load("c:\weather.xml")
Dim nav As XPathNavigator = doc.CreateNavigator()
nav.MoveToRoot() ' Start at the top
nav.MoveToFirstChild() ' Move to <weatherdata>
Do
If nav.HasChildren Then ' If weather data has child nodes
nav.MoveToFirstChild() ' Move to first child node
Do ' Cycle through child nodes
If nav.Name = "forecast" And nav.HasChildren Then ' Repeat steps when forecast found and look for time child nodes
nav.MoveToFirstChild()
Do ' Cycle child nodes
If nav.Name = "time" Then ' When the "time" node is found
sFrom = nav.GetAttribute("from", nav.NamespaceURI) ' Get value of "from" attribute
sFrom = sFrom.Substring(0, sFrom.IndexOf("T")) & " " & sFrom.Substring(sFrom.IndexOf("T") + 1) ' Format value for datetime
fDate = DateTime.ParseExact(sFrom, "yyyy-MM-dd HH:mm:ss", Nothing)
sTo = nav.GetAttribute("to", nav.NamespaceURI) ' Get value of "from" attribute
sTo = sTo.Substring(0, sTo.IndexOf("T")) & " " & sTo.Substring(sTo.IndexOf("T") + 1) ' Format value for datetime
tDate = DateTime.ParseExact(sTo, "yyyy-MM-dd HH:mm:ss", Nothing)
If (MyDate >= fDate) And (MyDate <= tDate) And nav.HasChildren Then
found = True ' found a match - this is just so a "Not Found" message isn't displayed at the end
nav.MoveToFirstChild() ' Start looking for tempature childe node
Do
If nav.Name = "temperature" Then
Console.WriteLine("The max temperature will be " & nav.GetAttribute("max", nav.NamespaceURI)) ' Print the value for max tempatures
End If
Loop While nav.MoveToNext
End If
End If
Loop While nav.MoveToNext
End If
Loop While nav.MoveToNext
End If
Loop While nav.MoveToNext
If found = False Then Console.WriteLine("Could not find tempature for date/time provided.") ' Not Found
Console.ReadLine()
End Sub
End Module
https://docs.microsoft.com/en-us/tro...avigator-class
-
Jan 11th, 2022, 04:51 AM
#3
Re: Navigating an XML structure - please help
If you use xPath like this...
Code:
Dim wc As New Net.WebClient
Dim newXML As XDocument = XDocument.Parse(wc.DownloadString("xml url"))
you'll download your XML as this..
Code:
<?xml version="1.0" encoding="UTF-8"?>
<weatherdata>
<location>
<name>Saline</name>
<type></type>
<country>US</country>
<timezone>-18000</timezone>
<location altitude="0" latitude="42.1698" longitude="-83.7849" geobase="geonames" geobaseid="0"></location>
</location>
<credit></credit>
<meta>
<lastupdate></lastupdate>
<calctime>0</calctime>
<nextupdate></nextupdate>
</meta>
<sun rise="2022-01-10T13:02:51" set="2022-01-10T22:22:06"></sun>
<forecast>
<time from="2022-01-11T03:00:00" to="2022-01-11T06:00:00">
<symbol number="803" name="broken clouds" var="04n"></symbol>
<precipitation probability="0"></precipitation>
<windDirection deg="304" code="NW" name="Northwest"></windDirection>
<windSpeed mps="3.86" unit="m/s" name="Gentle Breeze"></windSpeed>
<windGust gust="7.49" unit="m/s"></windGust>
<temperature unit="kelvin" value="260.06" min="260.06" max="260.14"></temperature>
<feels_like value="253.06" unit="kelvin"></feels_like>
<pressure unit="hPa" value="1035"></pressure>
<humidity value="71" unit="%"></humidity>
<clouds value="broken clouds" all="66" unit="%"></clouds>
<visibility value="10000"></visibility>
</time>
<time from="2022-01-11T06:00:00" to="2022-01-11T09:00:00">
<symbol number="802" name="scattered clouds" var="03n"></symbol>
<precipitation probability="0"></precipitation>
<windDirection deg="291" code="WNW" name="West-northwest"></windDirection>
<windSpeed mps="2.27" unit="m/s" name="Light breeze"></windSpeed>
<windGust gust="3.81" unit="m/s"></windGust>
<temperature unit="kelvin" value="260.25" min="260.25" max="260.37"></temperature>
<feels_like value="255.21" unit="kelvin"></feels_like>
<pressure unit="hPa" value="1035"></pressure>
<humidity value="74" unit="%"></humidity>
<clouds value="scattered clouds" all="29" unit="%"></clouds>
<visibility value="10000"></visibility>
</time>
</forecast>
</weatherdata>
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Jan 11th, 2022, 08:04 AM
#4
Re: Navigating an XML structure - please help
I would load all Data into a DataTable and Filter that, but thats up to you
here a sample to select from the structure
Code:
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Dim myDoc As XDocument
'myDoc = XDocument.Load("D:\Testfolder\grostonWeather.xml")
Dim myDoc As XDocument
myDoc = _
<?xml version="1.0" encoding="UTF-8"?>
<weatherdata>
<location>
<name>Saline</name>
<type></type>
<country>US</country>
<timezone>-18000</timezone>
<location altitude="0" latitude="42.1698" longitude="-83.7849" geobase="geonames" geobaseid="0"></location>
</location>
<credit></credit>
<meta>
<lastupdate></lastupdate>
<calctime>0</calctime>
<nextupdate></nextupdate>
</meta>
<sun rise="2022-01-10T13:02:51" set="2022-01-10T22:22:06"></sun>
<forecast>
<time from="2022-01-11T03:00:00" to="2022-01-11T06:00:00">
<symbol number="803" name="broken clouds" var="04n"></symbol>
<precipitation probability="0"></precipitation>
<windDirection deg="304" code="NW" name="Northwest"></windDirection>
<windSpeed mps="3.86" unit="m/s" name="Gentle Breeze"></windSpeed>
<windGust gust="7.49" unit="m/s"></windGust>
<temperature unit="kelvin" value="260.06" min="260.06" max="260.14"></temperature>
<feels_like value="253.06" unit="kelvin"></feels_like>
<pressure unit="hPa" value="1035"></pressure>
<humidity value="71" unit="%"></humidity>
<clouds value="broken clouds" all="66" unit="%"></clouds>
<visibility value="10000"></visibility>
</time>
<time from="2022-01-11T06:00:00" to="2022-01-11T09:00:00">
<symbol number="802" name="scattered clouds" var="03n"></symbol>
<precipitation probability="0"></precipitation>
<windDirection deg="291" code="WNW" name="West-northwest"></windDirection>
<windSpeed mps="2.27" unit="m/s" name="Light breeze"></windSpeed>
<windGust gust="3.81" unit="m/s"></windGust>
<temperature unit="kelvin" value="260.25" min="260.25" max="260.37"></temperature>
<feels_like value="255.21" unit="kelvin"></feels_like>
<pressure unit="hPa" value="1035"></pressure>
<humidity value="74" unit="%"></humidity>
<clouds value="scattered clouds" all="29" unit="%"></clouds>
<visibility value="10000"></visibility>
</time>
</forecast>
</weatherdata>
Dim DT As New DataTable
DT = AddDataColumns(DT)
For Each topNMElement As XElement In myDoc...<weatherdata>
Dim headerElement As XElement = topNMElement.<forecast>.Single
'For Each itemElement In headerElement...<time>
' 'add Windspeed and Max Temp. to DGV
' summaryDT.Rows.Add({itemElement.<windSpeed>.Attributes("mps").ElementAt(0).Value, _
' itemElement.<temperature>.Attributes("max").ElementAt(0).Value _
' })
For Each itemElement In headerElement...<time>
'add Time and Max Temp. to DGV
DT.Rows.Add({headerElement.<time>.Attributes("from").ElementAt(0).Value, _
itemElement.<temperature>.Attributes("max").ElementAt(0).Value _
})
Next
Next
DataGridView1.DataSource = DT
End Sub
Private Function AddDataColumns(ByVal DT As DataTable) As DataTable
With DT
.Columns.Add(New DataColumn("Time(from)", GetType(Date)))
.Columns.Add(New DataColumn("Max Temp.", GetType(String)))
End With
Return DT
End Function
to hunt a species to extinction is not logical !
since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.
-
Jan 12th, 2022, 10:25 AM
#5
Re: Navigating an XML structure - please help
I'd use XElement and LINQ.
The data
Code:
Dim data As XElement
'to load from site
' data=XElement.Load(url to data here)
'FOR TESTING you can use a literal
data = <weatherdata>
<location>
<name>Saline</name>
<type></type>
<country>US</country>
<timezone>-18000</timezone>
<location altitude="0" latitude="42.1698" longitude="-83.7849" geobase="geonames" geobaseid="0"></location>
</location>
<credit></credit>
<meta>
<lastupdate></lastupdate>
<calctime>0</calctime>
<nextupdate></nextupdate>
</meta>
<sun rise="2022-01-10T13:02:51" set="2022-01-10T22:22:06"></sun>
<forecast>
<time from="2022-01-11T03:00:00" to="2022-01-11T06:00:00">
<symbol number="803" name="broken clouds" var="04n"></symbol>
<precipitation probability="0"></precipitation>
<windDirection deg="304" code="NW" name="Northwest"></windDirection>
<windSpeed mps="3.86" unit="m/s" name="Gentle Breeze"></windSpeed>
<windGust gust="7.49" unit="m/s"></windGust>
<temperature unit="kelvin" value="260.06" min="260.06" max="260.14"></temperature>
<feels_like value="253.06" unit="kelvin"></feels_like>
<pressure unit="hPa" value="1035"></pressure>
<humidity value="71" unit="%"></humidity>
<clouds value="broken clouds" all="66" unit="%"></clouds>
<visibility value="10000"></visibility>
</time>
<time from="2022-01-11T06:00:00" to="2022-01-11T09:00:00">
<symbol number="802" name="scattered clouds" var="03n"></symbol>
<precipitation probability="0"></precipitation>
<windDirection deg="291" code="WNW" name="West-northwest"></windDirection>
<windSpeed mps="2.27" unit="m/s" name="Light breeze"></windSpeed>
<windGust gust="3.81" unit="m/s"></windGust>
<temperature unit="kelvin" value="260.25" min="260.25" max="260.37"></temperature>
<feels_like value="255.21" unit="kelvin"></feels_like>
<pressure unit="hPa" value="1035"></pressure>
<humidity value="74" unit="%"></humidity>
<clouds value="scattered clouds" all="29" unit="%"></clouds>
<visibility value="10000"></visibility>
</time>
</forecast>
</weatherdata>
And then the code to get the max temp,
Code:
Dim maxT As String
maxT = (From el In data.<forecast>...<time>
Let t1 As DateTimeOffset = DateTime.ParseExact(el.@from, "yyyy-MM-dd'T'HH:mm:ss", Globalization.CultureInfo.InvariantCulture)
Let t2 As DateTimeOffset = DateTime.ParseExact(el.@to, "yyyy-MM-dd'T'HH:mm:ss", Globalization.CultureInfo.InvariantCulture)
Let t3 As DateTime = #1/11/2022 4:00:00 AM#
Where t1 > t3 AndAlso t3 < t2
Select el.<temperature>.@max).FirstOrDefault
-
Jan 13th, 2022, 03:29 AM
#6
Re: Navigating an XML structure - please help
Originally Posted by dbasnett
I'd use XElement and LINQ.
The data
Code:
Dim data As XElement
'to load from site
' data=XElement.Load(url to data here)
'FOR TESTING you can use a literal
data = <weatherdata>
<location>
<name>Saline</name>
<type></type>
<country>US</country>
<timezone>-18000</timezone>
<location altitude="0" latitude="42.1698" longitude="-83.7849" geobase="geonames" geobaseid="0"></location>
</location>
<credit></credit>
<meta>
<lastupdate></lastupdate>
<calctime>0</calctime>
<nextupdate></nextupdate>
</meta>
<sun rise="2022-01-10T13:02:51" set="2022-01-10T22:22:06"></sun>
<forecast>
<time from="2022-01-11T03:00:00" to="2022-01-11T06:00:00">
<symbol number="803" name="broken clouds" var="04n"></symbol>
<precipitation probability="0"></precipitation>
<windDirection deg="304" code="NW" name="Northwest"></windDirection>
<windSpeed mps="3.86" unit="m/s" name="Gentle Breeze"></windSpeed>
<windGust gust="7.49" unit="m/s"></windGust>
<temperature unit="kelvin" value="260.06" min="260.06" max="260.14"></temperature>
<feels_like value="253.06" unit="kelvin"></feels_like>
<pressure unit="hPa" value="1035"></pressure>
<humidity value="71" unit="%"></humidity>
<clouds value="broken clouds" all="66" unit="%"></clouds>
<visibility value="10000"></visibility>
</time>
<time from="2022-01-11T06:00:00" to="2022-01-11T09:00:00">
<symbol number="802" name="scattered clouds" var="03n"></symbol>
<precipitation probability="0"></precipitation>
<windDirection deg="291" code="WNW" name="West-northwest"></windDirection>
<windSpeed mps="2.27" unit="m/s" name="Light breeze"></windSpeed>
<windGust gust="3.81" unit="m/s"></windGust>
<temperature unit="kelvin" value="260.25" min="260.25" max="260.37"></temperature>
<feels_like value="255.21" unit="kelvin"></feels_like>
<pressure unit="hPa" value="1035"></pressure>
<humidity value="74" unit="%"></humidity>
<clouds value="scattered clouds" all="29" unit="%"></clouds>
<visibility value="10000"></visibility>
</time>
</forecast>
</weatherdata>
And then the code to get the max temp,
Code:
Dim maxT As String
maxT = (From el In data.<forecast>...<time>
Let t1 As DateTimeOffset = DateTime.ParseExact(el.@from, "yyyy-MM-dd'T'HH:mm:ss", Globalization.CultureInfo.InvariantCulture)
Let t2 As DateTimeOffset = DateTime.ParseExact(el.@to, "yyyy-MM-dd'T'HH:mm:ss", Globalization.CultureInfo.InvariantCulture)
Let t3 As DateTime = #1/11/2022 4:00:00 AM#
Where t1 > t3 AndAlso t3 < t2
Select el.<temperature>.@max).FirstOrDefault
I like it
to hunt a species to extinction is not logical !
since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.
-
Jan 18th, 2022, 12:20 PM
#7
Thread Starter
Lively Member
Re: Navigating an XML structure - please help
Tewl: Thanks. I tried your code and it worked, but only kinda. When I did not include the code for finding the temperature, the code looped through the entire XML. However, once I added the temperature code, it would show the first temperature, then simply quit looping. Here is my code:
Code:
Do
If nav.HasChildren Then ' If weather data has child nodes
nav.MoveToFirstChild() ' Move to first child node
Do ' Cycle through child nodes
If nav.Name = "forecast" And nav.HasChildren Then ' Repeat steps when forecast found and look for time child nodes
nav.MoveToFirstChild()
Do ' Cycle child nodes
If nav.Name = "time" Then ' When the "time" node is found
sFrom = nav.GetAttribute("from", nav.NamespaceURI) ' Get value of "from" attribute
nav.MoveToFirstChild() ' Start looking for tempature childe node
Do
If nav.Name = "temperature" Then
sTemp = nav.GetAttribute("max", nav.NamespaceURI) ' Get value of temperatures
End If
Loop While nav.MoveToNext
End If
Loop While nav.MoveToNext ' breakpoint here
End If
Loop While nav.MoveToNext
End If
Loop While nav.MoveToNext
and I put a breakpoint where shown.
-
Jan 18th, 2022, 02:11 PM
#8
Re: Navigating an XML structure - please help
-
Jan 18th, 2022, 06:30 PM
#9
Thread Starter
Lively Member
Re: Navigating an XML structure - please help
I believe that I am making some progress. I tweaked the code provided to this:
Code:
Dim elemWeather As XElement = myDoc.Root
Dim elemForecast As XElement = elemWeather.<forecast>.Single
For Each elemTime As XElement In elemForecast.Descendants
sFrom = elemTime.Attributes("from").ElementAt(0).Value ' marked line
For Each elemData As XElement In elemTime.Descendants
If elemData.Name = "temperature" Then
sTemp = elemTime.<temperature>.Attributes("max").ElementAt(0).Value
End If
Next
Next
It works fine, and gets the time and temperature values, but as soon as the marked line is hit the second time, I get the error "Specified argument was out of the range of valid values." I suspect that not more than a small change is needed... please help.
-
Jan 18th, 2022, 06:46 PM
#10
Re: Navigating an XML structure - please help
This should run...
Code:
Dim elemWeather As XElement = myDoc.Root
Dim elemForecast As XElement = elemWeather.<forecast>.Single
For Each elemTime As XElement In elemForecast.Descendants
sFrom = elemTime.Attributes("from").ElementAtOrDefault(0).Value ' marked line
For Each elemData As XElement In elemTime.Descendants
If elemData.Name = "temperature" Then
sTemp = elemTime.<temperature>.Attributes("max").ElementAtOrDefault(0).Value
End If
Next
Next
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Jan 18th, 2022, 06:53 PM
#11
Thread Starter
Lively Member
Re: Navigating an XML structure - please help
.paul - thanks for the prompt reply, but it didn't work. When the marked line was hit the second time, I got the error "Object reference not set to an instance of an object."
-
Jan 18th, 2022, 06:58 PM
#12
Re: Navigating an XML structure - please help
Try this...
Code:
Dim elemWeather As XElement = myDoc.Root
Dim elemForecast As XElement = elemWeather.<forecast>.Single
For Each elemTime As XElement In elemForecast.Descendants
If elemTime.Attributes("from") IsNot Nothing Then
sFrom = elemTime.Attributes("from").ElementAtOrDefault(0).Value ' marked line
End If
For Each elemData As XElement In elemTime.Descendants
If elemData.Name = "temperature" Then
If elemTime.<temperature>.Attributes("max") IsNot Nothing Then
sTemp = elemTime.<temperature>.Attributes("max").ElementAtOrDefault(0).Value
End If
End If
Next
Next
- Coding Examples:
- Features:
- Online Games:
- Compiled Games:
-
Jan 18th, 2022, 10:57 PM
#13
Thread Starter
Lively Member
Re: Navigating an XML structure - please help
Good idea, but I got the same error. I expanded elemTime.Attributes("from") in the debugger, and the Value was XmlQuery. I clicked the + and saw Name: Results, Value: Expanding will process the collection. When I clicked the + again, I saw Name: Empty, Value: Enumeration yielded no results.
-
Jan 19th, 2022, 05:54 PM
#14
Thread Starter
Lively Member
Re: Navigating an XML structure - please help
Problem solved: Replace elemForecast.Descendants with elemForecast.Elements.
-
Jan 20th, 2022, 10:13 AM
#15
Re: Navigating an XML structure - please help
Originally Posted by groston
Problem solved: Replace elemForecast.Descendants with elemForecast.Elements.
It was solved in post 5...
-
Jan 20th, 2022, 04:20 PM
#16
Re: Navigating an XML structure - please help
Originally Posted by groston
Tewl: Thanks. I tried your code and it worked, but only kinda.
Post#4 loads all, and like I said you Filter after
Post#5 has the Filter included
so explain what you mean with but only kinda.
to hunt a species to extinction is not logical !
since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|