A few questions about XML

Blake81

Well-known member
Joined
Feb 23, 2006
Messages
304
Location
Georgia, USA
Programming Experience
1-3
Hi,

I'm just learning VB, and I have a few questions. For the app I'm developing, I am accessing a website that's in XML format and for now I'm saving it to a file. I'd like to have my application save it to an array and have the information accessed from there, but I can't seem to figure out how to do it. An even better idea, if possible, would be to analyze each piece being downloaded, and only save it to the array if it's a certain XML line. I'm making a program to look up XML weather by zip code, so for example, I'd like it to only save a few lines. Here are some examples:
<tmp>53</tmp>
<flik>53</flik>

<t>Cloudy</t>

Thanks for any help. I've been looking online alot, but haven't found answers
 
I have a possible solution, but I have two questions about it. Can I download the text of a URL and put it in a Textbox? If that's possible, can I treat Textbox1.Text as an XML document? I looked at that link you gave me, but it doesn't say anything about the XML document being online, so I'm not sure how to use it.
 
Thanks. I tried using the load method and I think I'm not specifying what I want in the XML correctly. I'm not really sure what I'm doing wrong. In those examples, they already knew what the inner XML was, and I don't in my situation. Any ideas how I could get the inner XML for <cc></cc> and all its child nodes? Here's what I have tried.
PrivateSub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim xmldocument AsNew Xml.XmlDocument
xmldocument.Load(
"The URL is here, but I'll leave it out for this post")
xmldocument.LoadXml(
"<cc>" & "</cc>")
EndSub
Dim
Xnodes As System.Xml.XmlNodeList
Dim Xnode As System.Xml.XmlNode
Xnodes = xmldocument.SelectNodes(
"/weather/cc/")
ForEach Xnode In Xnodes
'ComboBox1.Items.Add(Xnode.InnerXml())
If Xnode.Name = "obst"Then
ComboBox1.Items.Add(Xnode.Value())
ElseIf Xnode.Name = "tmp"Then
ComboBox1.Items.Add(Xnode.Value())
ElseIf Xnode.Name = "flik"Then
ComboBox1.Items.Add(Xnode.Value())
EndIf
Next

Actually it would be the sibling nodes of <cc> (I think). Here's the XML for that part:
- <cc>
<lsup>2/23/06 10:00 PM EST</lsup>

<obst>City Name Here</obst>

<tmp>39</tmp>

<flik>39</flik>

<t>Partly Cloudy</t>

<icon>29</icon>

- <bar>
<r>30.26</r>

<d>steady</d>

</bar>


- <wind>
<s>calm</s>

<gust>N/A</gust>

<d>0</d>

<t>CALM</t>

</wind>


<hmid>82</hmid>

<vis>10.0</vis>

- <uv>
<i>0</i>

<t>Low</t>

</uv>


<dewp>34</dewp>

- <moon>
<icon>25</icon>

<t>Waning Crescent</t>

</moon>


</cc>


 
Last edited:
This is very close. The thing you are missing is that SelectNodes returns all of the nodes matching the string you specify. In your case this is the one node "/weather/cc". So your For Each Look is still working at the wrong level of the XML tree. You may want to try something more like this:

Dim Rootnode As System.Xml.XmlNode
Dim Xnode As System.Xml.XmlNode
Rootnode = xmldocument.SelectSingleNode(
"/weather/cc/")
For
Each Xnode In RootNode.ChildNodes
 
Thank you. :) I figured it out. Step debugging is good. It helped me figure out the relationships (sibling/child nodes, etc.) This is part of what I ended up with and it works.
Dim Xnode As System.Xml.XmlNodeList
Dim Xnodes As System.Xml.XmlNode
Xnodes = xmldocument.SelectSingleNode(
"/weather/cc")
Xnode = Xnodes.ChildNodes
For Each Xnodes In Xnode
If Xnodes.Name = "obst" Then
ComboBox1.Items.Add(Xnodes.FirstChild.InnerText())


It turns out that since I was changing little pieces at a time, my Xnode and Xnodes variable names are a little backwards, but it still works. Thank you for your help.
 
Good news. I always say that learning VB.NET is 10% language and 90% framework myself. The framework has so many good things in it. But, they can be hard to find when you first start out.
 
Thank you for your help. I really appreciate it. Actually, I have another question about the same project. Part of the XML has a 5 day forecast starting with day 0 (which is actually the current day, so I'm trying to skip it). That first line referring to the day is confusing me, especially since it has a few attributes. Here's what the line looks like.
<day d="0" t="Friday" dt="Feb 24">

How would I get it to go to each line from 1 to 5 so I can run my conditions to get specific information in their child nodes? Also, I have something I came up with to try to skip day 0, but I haven't tested it yet, so any suggestions would be good. Thanks for your help. :)
 
You didn't show what this entry is inside of. I' assume it is something like:

<forecast>
<day d="0" ...>
... more subnodes....
</day>
<day d="1" ...>
.
.
.
<day d="5" ...>
... more subnodes....
</day>
</forecast>

If this is the case you can get each node by doing what you originally were doing wrong the first time. Use the SelectNodes("/forecast/day"). Now you will get a collection of the day Nodes. You can use the Attributes property on each node to check the value of the "d" attribute and then you can use the ChildNodes to access all of the data under each day.
 
Here's all of the XML up to the first day and one line under it. The attribute thing is new to me, so I'm not sure how that works. What would it return since there are three parts to that attribute, or are those considered three seperate attributes?
<?xml version="1.0" encoding="ISO-8859-1" ?>
- <!-- This document is intended only for use by authorized licensees of The Weather Channel. Unauthorized use is prohibited. Copyright 1995-2005, The Weather Channel Interactive, Inc. All Rights Reserved. -->f(clean);
- <weather ver="2.0">
- <head>
<locale>en_US</locale>

<form>MEDIUM</form>

<ut>F</ut>

<ud>mi</ud>

<us>mph</us>

<up>in</up>

<ur>in</ur>

</head>


- <loc id="30117">
<dnam>City Name Here</dnam>

<tm>8:04 AM</tm>

<lat>33.58</lat>

<lon>-85.1</lon>

<sunr>7:15 AM</sunr>

<suns>6:33 PM</suns>

<zone>-5</zone>

</loc>


- <cc>
<lsup>2/24/06 7:45 AM EST</lsup>

<obst>City Name Here</obst>

<tmp>31</tmp>

<flik>31</flik>

<t>Partly Cloudy</t>

<icon>30</icon>

- <bar>
<r>30.40</r>

<d>rising</d>

</bar>


- <wind>
<s>1</s>

<gust>N/A</gust>

<d>10</d>

<t>NNE</t>

</wind>


<hmid>90</hmid>

<vis>10.0</vis>

- <uv>
<i>0</i>

<t>Low</t>

</uv>


<dewp>29</dewp>

- <moon>
<icon>25</icon>

<t>Waning Crescent</t>

</moon>


</cc>


- <dayf>
<lsup>2/24/06 6:07 AM EST</lsup>

- <day d="0" t="Friday" dt="Feb 24">
<hi>67</hi>
 
I'm still having trouble with this. I found the GetAttribute method, but I'm not sure how to use it. Here's some of the code I've been using. Some of it is just stuff I've been trying to see if I can get it to work. That's why some things are commented out.
Dim Fxml As New System.Xml.XmlDocument
Fxml =
New System.Xml.XmlDocument
Fxml.Load(
"http://xoap.weather.com/weather/local/30117?cc=*&dayf=5&prod=xoap&par=1017300893&key=268086eb4218acff")
Dim Fnodes As System.Xml.XmlNodeList
Dim Fnode As System.Xml.XmlNode
Dim NodeNav As System.Xml.XPath.XPathNavigator = Fxml.CreateNavigator
Dim Value1 As String
Fnode = Fxml.SelectSingleNode("/weather/dayf/day")
Value1 = NodeNav.NamespaceURI
'NodeNav.MoveToAttribute("d", "http://xoap.weather.com/weather/local/30117?cc=*&dayf=5&prod=xoap&par=1017300893&key=268086eb4218acff")
'MessageBox.Show(Fnode.Value)
Dim FSib As System.Xml.XmlNode = Fnode.NextSibling
Fnodes = Fnode.ChildNodes
Dim x As Integer = 1
'For x = 1 To 5
'MessageBox.Show(FSib.Name)
Dim Att As String = NodeNav.MoveToAttribute("d", FSib.NamespaceURI)
MessageBox.Show(NodeNav.)
For Each Fnode In Fnodes
If Fnode.Name = "hi" Then
MessageBox.Show(Fnode.Name)
ElseIf Fnode.Name = "low" Then
MessageBox.Show(Fnode.Name)
End If
MessageBox.Show(FSib.Name, FSib.InnerText)
Next
 
You should have provided better info about the source file to begin with, ie the link in your previous post.

Here is one example getting info out of there, I just put it all into a StringBuilder to display a messagebox, you would probably put the different info into labels or textboxes etc.

Of course I only get a few values for this example, location and current weather, some info about forecasts each day, run it and have a look at how it displays.

Notice the two different methods I use to access attributes, there is the Attributes property (with overloads for access by index or string identifier) and you can use a regular Xpath expression to select node/attribute. The "@" signifies an attribute in Xpath, and I'm using this as an qualifier when getting the appropriate daytime/nighttime node of each forecast day.
VB.NET:
Sub xmlexample()
  Dim sb As New System.Text.StringBuilder
  Dim xdoc As New Xml.XmlDocument
  xdoc.Load("http://xoap.weather.com/weather/local/30117?cc=*&dayf=5&prod=xoap&par=1017300893&key=268 086eb4218acff")
  Dim xroot As Xml.XmlElement = xdoc.DocumentElement
  Dim xnode As Xml.XmlNode = xroot.SelectSingleNode("cc")
  sb.AppendLine("location: " & xnode.SelectSingleNode("obst").InnerText)
  sb.AppendLine("current weather: " & xnode.SelectSingleNode("t").InnerText)
  sb.AppendLine("forecasts: ")
  sb.AppendLine()
  For Each day As Xml.XmlNode In xroot.SelectNodes("dayf/day")
    sb.Append(vbTab & day.Attributes("t").InnerText & ", ")
    sb.AppendLine(day.Attributes("dt").Value)
    sb.AppendLine(vbTab & "hi: " & day.SelectSingleNode("hi").InnerText)
    sb.AppendLine(vbTab & "low: " & day.SelectSingleNode("low").InnerText)
    sb.AppendLine(vbTab & "sunrise: " & day.SelectSingleNode("sunr").InnerText)
    sb.AppendLine(vbTab & "sunset: " & day.SelectSingleNode("suns").InnerText)
    sb.Append(vbTab & "day: ")
    sb.AppendLine(vbTab & "weather: " & day.SelectSingleNode("part[@p='d']/t").InnerText)
    sb.AppendLine(vbTab & vbTab & "humidity: " & day.SelectSingleNode("part[@p='d']/hmid").InnerText)
    sb.Append(vbTab & "night: ")
    sb.AppendLine(vbTab & "weather: " & day.SelectSingleNode("part[@p='n']/t").InnerText)
    sb.AppendLine(vbTab & vbTab & "humidity: " & day.SelectSingleNode("part[@p='n']/hmid").InnerText)
    sb.AppendLine()
  Next
  MsgBox(sb.ToString)
End Sub
 
Back
Top