从XML获取特定数据

时间:2014-01-31 22:22:59

标签: xml vb.net rss

我是VB和.NET的新手,我在设置天气小工具时遇到了麻烦。我从Yahoos RSS提要中提取,存储到XML文件,然后从该XML文件中读取。前几件事情很好,但雅虎的饲料基本上发回了天/临时/高/低的列表。 (见下文)

<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>

我遇到麻烦的地方就是这个

<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"/>

如您所见,它提供了一个日期和值列表。我在将这些值读入变量/标签时遇到了麻烦。例如,我一直在尝试

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

尝试为每个_dayOfWeek获取低 - 但我继续收回XPathExceptions,未关闭的字符串,所以这听起来像我采取的路径是一个没有'+ _dayOfWeek'的完整字符串 - 我是gonig有为每周的不同日期创建子程序???

如果你能看到我正在做的任何蠢事,请告诉我,这是我的参考代码

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

2 个答案:

答案 0 :(得分:1)

如果上面是你真正的代码,我认为问题是关闭方括号的单引号:

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

我怀疑它应该是这样的:

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

或者复制粘贴代码只是一个错误?

答案 1 :(得分:0)

我发现了一种不同的方式,因为我总是在寻找接下来的3天,而不是随机/可变的天数

所以而不是

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

并递增_dayOfWeek,你可以跳过递增,完全摆脱_dayOfWeek你可以实际使用

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

这将允许你在第0天获得低点(我猜XML节点从1开始,而不是0) - 然后你可以迭代并获得第1个,第2个的低/高/代码,以及第三天。

我花了大约一天的时间来运行这个Yahoo RSS feed天气小部件,如果有人想看到它的最终代码,请点击此处。

 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