Getting Specific Data from XML

↘锁芯ラ 提交于 2020-01-16 05:51:41

问题


I 'm kind of new to VB and .NET, and I'm having trouble especially with trying to setup a weather widget. I'm pulling from Yahoos RSS feeds, storing to an XML file, and then reading from that XML file. The first couple of things pull in fine, but Yahoo's feed sends back basically a LIST of days/temps/highs/lows. (see below)

<rss xmlns:yweather="http://xml.weather.yahoo.com/ns/rss/1.0" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" version="2.0">
<channel>
<title>Yahoo! Weather - Lincoln, NE</title>
<link>...</link>
<description>Yahoo! Weather for Lincoln, NE</description>
<language>en-us</language>
<lastBuildDate>Fri, 31 Jan 2014 12:53 pm CST</lastBuildDate>
<ttl>60</ttl>
<yweather:location city="Lincoln" region="NE" country="US"/>
<yweather:units temperature="F" distance="mi" pressure="in" speed="mph"/>
<yweather:wind chill="13" direction="80" speed="7"/>
<yweather:atmosphere humidity="43" visibility="10" pressure="30.08" rising="2"/>
<yweather:astronomy sunrise="7:37 am" sunset="5:43 pm"/>
<image>...</image>
<item>
<title>Conditions for Lincoln, NE at 12:53 pm CST</title>
<geo:lat>40.8</geo:lat>
<geo:long>-96.67</geo:long>
<link>
http://us.rd.yahoo.com/dailynews/rss/weather/Lincoln__NE/*http://weather.yahoo.com/forecast/USNE0283_f.html
</link>
<pubDate>Fri, 31 Jan 2014 12:53 pm CST</pubDate>
<yweather:condition text="Cloudy" code="26" temp="22" date="Fri, 31 Jan 2014 12:53 pm CST"/>
<description>
<![CDATA[...]]>
</description>
<yweather:forecast day="Fri" date="31 Jan 2014" low="18" high="25" text="Few Snow Showers" code="14"/>
<yweather:forecast day="Sat" date="1 Feb 2014" low="5" high="31" text="AM Clouds/PM Sun" code="30"/>
<yweather:forecast day="Sun" date="2 Feb 2014" low="11" high="27" text="Sunny" code="32"/>
<yweather:forecast day="Mon" date="3 Feb 2014" low="18" high="36" text="Partly Cloudy" code="30"/>
<yweather:forecast day="Tue" date="4 Feb 2014" low="-3" high="21" text="Snow Showers" code="14"/>
<guid isPermaLink="false">USNE0283_2014_02_04_7_00_CST</guid>
</item>
</channel>
</rss>

The area I'm having trouble is this

<yweather:forecast day="Fri" date="31 Jan 2014" low="18" high="25" text="Few Snow Showers" code="14"/>
<yweather:forecast day="Sat" date="1 Feb 2014" low="5" high="31" text="AM Clouds/PM Sun" code="30"/>
<yweather:forecast day="Sun" date="2 Feb 2014" low="11" high="27" text="Sunny" code="32"/>
<yweather:forecast day="Mon" date="3 Feb 2014" low="18" high="36" text="Partly Cloudy" code="30"/>
<yweather:forecast day="Tue" date="4 Feb 2014" low="-3" high="21" text="Snow Showers" code="14"/>

As you can see, it gives a list of dates and values back. I'm having trouble reading those values into variables/labels. For example I've been trying

MyDoc.SelectSingleNode("/rss/channel/item/yweather:forecast[day='" + _dayOfweek + "']/@low", nsmgr).InnerText

To try and get the low for each _dayOfWeek -- but I keep getting back XPathExceptions, unclosed strings, so it sounds like the path I take HAS to be a full string with no ' + _dayOfWeek ' - Am I gonig to have to create subroutines for each different day of the week???

Please let me know if you can see anything dumb that I'm doing, here's my code for reference

Public Class CtrlWeatherWidget
    ReadOnly _zip = 68508
    'In the future, may want to include options to view multiple locations, in which case this won't be read only
    Dim _conditions
    Dim _dayOfWeek As String

    Public Sub Update()

        Dim rssurl = "http://xml.weather.yahoo.com/forecastrss?p=" + _zip.ToString()
        Dim rssrequest As Net.WebRequest = Net.WebRequest.Create(rssurl)

        Dim rssresponse As Net.WebResponse = rssrequest.GetResponse()
        Dim rssstream As IO.Stream = rssresponse.GetResponseStream()

        Dim rssdoc As New Xml.XmlDocument
        rssdoc.Load(rssstream)

        Dim nodes As Xml.XmlNodeList
        nodes = rssdoc.SelectNodes("/rss/channel")

        lblCityState.Text = Replace(nodes.Item(0).SelectSingleNode("title").InnerText, "Yahoo! Weather - ", "")

        Dim nsmgr = New Xml.XmlNamespaceManager(rssdoc.NameTable)
        nsmgr.AddNamespace("yweather", "http://xml.weather.yahoo.com/ns/rss/1.0")

        'find the conditions and display the correct image for the current weather

        _conditions = rssdoc.SelectSingleNode("/rss/channel/item/yweather:condition/@code", nsmgr).InnerText

        picConditions.BackgroundImage = GetConditions()

        'get the current days highs and lows and picture

        lblCurrentTemp.Text = rssdoc.SelectSingleNode("rss/channel/item/yweather:condition/@temp", nsmgr).InnerText

        lblLowNow.Text = rssdoc.SelectSingleNode("/rss/channel/item/yweather:forecast[day='" + _dayOfWeek + "']'/@low", nsmgr).InnerText
        'Tabel/Member[Naam='Ghostbullet93']/Kills"
        lblHighNow.Text = rssdoc.SelectSingleNode("/rss/channel/item/yweather:forecast[day='" + _dayOfWeek + "']'/@high", nsmgr).InnerText

        'set the 3 days in the future information below, and get lows highs, picture

        GetDay(1)
        lblDayOne.Text = _dayOfWeek
        _conditions = rssdoc.SelectSingleNode("rss/channel/yweather:condition/@temp", nsmgr).InnerText
        picDayOne.BackgroundImage = GetConditions()
        lblHighOne.Text = String.Format("H: {0}", rssdoc.SelectSingleNode("rss/channel/yweather:atmosphere/@humidity", nsmgr).InnerText)
        lblLowOne.Text = String.Format("L: {0}", rssdoc.SelectSingleNode("rss/channel/yweather:atmosphere/@humidity", nsmgr).InnerText)

        GetDay(2)
        lblDayTwo.Text = _dayOfWeek
        _conditions = rssdoc.SelectSingleNode("rss/channel/yweather:condition/@temp", nsmgr).InnerText
        picDayTwo.BackgroundImage = GetConditions()
        lblHighTwo.Text = String.Format("H: {0}", rssdoc.SelectSingleNode("rss/channel/yweather:atmosphere/@humidity", nsmgr).InnerText)
        lblLowTwo.Text = String.Format("L: {0}", rssdoc.SelectSingleNode("rss/channel/yweather:atmosphere/@humidity", nsmgr).InnerText)

        GetDay(3)
        lblDayThree.Text = _dayOfWeek
        _conditions = rssdoc.SelectSingleNode("rss/channel/yweather:condition/@temp", nsmgr).InnerText
        picDayThree.BackgroundImage = GetConditions()
        lblHighThree.Text = String.Format("H: {0}", rssdoc.SelectSingleNode("rss/channel/yweather:atmosphere/@humidity", nsmgr).InnerText)
        lblLowThree.Text = String.Format("L: {0}", rssdoc.SelectSingleNode("rss/channel/yweather:atmosphere/@humidity", nsmgr).InnerText)

        lblUpdated.Text = String.Format("Last Updated {0}", Replace(nodes.Item(0).SelectSingleNode("rss/channel/item/title").InnerText, "Conditions for ", ""))

    End Sub

    Public Sub GetDay(ByVal offset As Integer)
        Dim day As Integer

        day = Date.Now.DayOfWeek

        If (day + offset) > 7 Then
            day = day + offset
            day = day - 7
        End If

        Select Case day
            Case 1
                _dayOfWeek = "Mon"
            Case 2
                _dayOfWeek = "Tue"
            Case 3
                _dayOfWeek = "Wed"
            Case 4
                _dayOfWeek = "Thu"
            Case 5
                _dayOfWeek = "Fri"
            Case 6
                _dayOfWeek = "Sat"
            Case 7
                _dayOfWeek = "Sun"
        End Select
    End Sub

    Public Function GetConditions() As Image
        If (_conditions >= 0 AndAlso _conditions <= 4) Or (_conditions >= 9 AndAlso _conditions <= 12) Or (_conditions >= 37 AndAlso _conditions <= 40) Or _conditions = 45 Or _conditions = 47 Then
            Return My.Resources.raining
        ElseIf (_conditions >= 5 AndAlso _conditions <= 8) Or (_conditions >= 13 AndAlso _conditions <= 16) Or (_conditions >= 41 AndAlso _conditions <= 43) Or _conditions = 46 Then
            Return My.Resources.snow
        ElseIf _conditions = 26 Then
            Return My.Resources.overcast_sky
        ElseIf _conditions = 27 Or _conditions = 29 Then
            Return My.Resources.night_partlycloudy
        ElseIf _conditions = 28 Or _conditions = 30 Or _conditions = 44 Then
            Return My.Resources.day_partlyCloudy
        ElseIf _conditions = 31 Or _conditions = 33 Then
            Return My.Resources.moon
        ElseIf _conditions = 32 Or _conditions = 34 Or _conditions = 36 Then
            Return My.Resources.day_clear
        Else
            Return My.Resources.overcast_sky
        End If
    End Function

    Private Sub btnUpdate_Click(sender As System.Object, e As EventArgs) Handles btnUpdate.Click
        Update()
    End Sub

End Class

回答1:


if above is your real code, I think the problem is single quotes around closing square bracket :

lblLowNow.Text = rssdoc.SelectSingleNode( _
                    "/rss/channel/item/yweather:forecast[day='" + _
                        _dayOfWeek + "']'/@low", nsmgr _
                    ).InnerText

I suspect it should be something like this instead :

lblLowNow.Text = rssdoc.SelectSingleNode( _
                    "/rss/channel/item/yweather:forecast[day='" + _
                        _dayOfWeek + "']/@low", nsmgr _
                    ).InnerText

or is it just a mistake when copy-paste the codes ?




回答2:


I found a different way to do it since I'm always looking for just the next 3 days rather than a random/variable number of days

So instead of

MyDoc.SelectSingleNode("/rss/channel/item/yweather:forecast[day='" + _dayOfweek + "']/@low", nsmgr).InnerText

and incrementing the _dayOfWeek, you can skip incrementing, get rid of _dayOfWeek entirely you can actually use

MyDoc.SelectSingleNode("//item/yweather:forecast[1]/@low", nsmgr).InnerText) 

and that will allow you to get the low for the 0th day (I guess XML nodes start at 1, not 0)- then you can just iterate over and get the low/high/code for the 1st, 2nd, and third days.

It took me about a day to get this Yahoo RSS feed weather widget running, if anyone wants to see the final code for it, here you go.

 Public Sub Update()

        Dim rssurl = "http://xml.weather.yahoo.com/forecastrss?p=" + _zip.ToString()
        Dim rssrequest As Net.WebRequest = Net.WebRequest.Create(rssurl)

        Dim rssresponse As Net.WebResponse = rssrequest.GetResponse()
        Dim rssstream As IO.Stream = rssresponse.GetResponseStream()

        Dim rssdoc As New Xml.XmlDocument
        rssdoc.Load(rssstream)

        Dim nodes As Xml.XmlNodeList
        nodes = rssdoc.SelectNodes("/rss/channel")

        lblCityState.Text = Replace(nodes.Item(0).SelectSingleNode("title").InnerText, "Yahoo! Weather - ", "")

        Dim nsmgr = New Xml.XmlNamespaceManager(rssdoc.NameTable)
        nsmgr.AddNamespace("yweather", "http://xml.weather.yahoo.com/ns/rss/1.0")

        'find the conditions and display the correct image for the current weather

        _conditions = rssdoc.SelectSingleNode("/rss/channel/item/yweather:condition/@code", nsmgr).InnerText

        picConditions.BackgroundImage = GetConditions()

        'get the current days highs and lows and picture

        lblCurrentTemp.Text = rssdoc.SelectSingleNode("//item/yweather:condition/@temp", nsmgr).InnerText
        lblLowNow.Text = String.Format("L: {0}", rssdoc.SelectSingleNode("//item/yweather:forecast[1]/@low", nsmgr).InnerText)
        lblHighNow.Text = String.Format("H: {0}", rssdoc.SelectSingleNode("//item/yweather:forecast[1]/@high", nsmgr).InnerText)
        'set the 3 days in the future information below, and get lows highs, picture

        lblDayOne.Text = rssdoc.SelectSingleNode("//item/yweather:forecast[2]/@day", nsmgr).InnerText
        _conditions = rssdoc.SelectSingleNode("//item/yweather:forecast[2]/@code", nsmgr).InnerText
        picDayOne.BackgroundImage = GetConditions()
        lblHighOne.Text = String.Format("H: {0}", rssdoc.SelectSingleNode("//item/yweather:forecast[2]/@low", nsmgr).InnerText)
        lblLowOne.Text = String.Format("L: {0}", rssdoc.SelectSingleNode("//item/yweather:forecast[2]/@high", nsmgr).InnerText)

        lblDayTwo.Text = rssdoc.SelectSingleNode("//item/yweather:forecast[3]/@day", nsmgr).InnerText
        _conditions = rssdoc.SelectSingleNode("//item/yweather:forecast[3]/@code", nsmgr).InnerText
        picDayTwo.BackgroundImage = GetConditions()
        lblHighTwo.Text = String.Format("H: {0}", rssdoc.SelectSingleNode("//item/yweather:forecast[3]/@high", nsmgr).InnerText)
        lblLowTwo.Text = String.Format("L: {0}", rssdoc.SelectSingleNode("//item/yweather:forecast[3]/@low", nsmgr).InnerText)

        lblDayThree.Text = rssdoc.SelectSingleNode("//item/yweather:forecast[4]/@day", nsmgr).InnerText
        _conditions = rssdoc.SelectSingleNode("//item/yweather:forecast[4]/@code", nsmgr).InnerText
        picDayThree.BackgroundImage = GetConditions()
        lblHighThree.Text = String.Format("H: {0}", rssdoc.SelectSingleNode("//item/yweather:forecast[4]/@high", nsmgr).InnerText)
        lblLowThree.Text = String.Format("L: {0}", rssdoc.SelectSingleNode("//item/yweather:forecast[4]/@low", nsmgr).InnerText)

        lblUpdated.Text = String.Format("Updated {0}", rssdoc.SelectSingleNode("//item/yweather:condition/@date", nsmgr).InnerText)

    End Sub

    Public Function GetConditions() As Image
        If (_conditions >= 0 AndAlso _conditions <= 4) Or (_conditions >= 9 AndAlso _conditions <= 12) Or (_conditions >= 37 AndAlso _conditions <= 40) Or _conditions = 45 Or _conditions = 47 Then
            Return My.Resources.raining
        ElseIf (_conditions >= 5 AndAlso _conditions <= 8) Or (_conditions >= 13 AndAlso _conditions <= 16) Or (_conditions >= 41 AndAlso _conditions <= 43) Or _conditions = 46 Then
            Return My.Resources.snow
        ElseIf _conditions = 26 Then
            Return My.Resources.overcast_sky
        ElseIf _conditions = 27 Or _conditions = 29 Then
            Return My.Resources.night_partlycloudy
        ElseIf _conditions = 28 Or _conditions = 30 Or _conditions = 44 Then
            Return My.Resources.day_partlyCloudy
        ElseIf _conditions = 31 Or _conditions = 33 Then
            Return My.Resources.moon
        ElseIf _conditions = 32 Or _conditions = 34 Or _conditions = 36 Then
            Return My.Resources.day_clear
        Else
            Return My.Resources.overcast_sky
        End If
    End Function

    Private Sub btnUpdate_Click(sender As System.Object, e As EventArgs) Handles btnUpdate.Click
        Update()
    End Sub

    Private Sub CtrlWeatherWidget_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Update()
        sleepTimer.Start()
    End Sub

    Private Sub sleepTimer_Tick(sender As System.Object, e As System.EventArgs) Handles sleepTimer.Tick
        Update()
    End Sub


来源:https://stackoverflow.com/questions/21491197/getting-specific-data-from-xml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!