You could load data from xml file into XmlDocument, then add new xml data and save to the same file again.
Something like this:
XmlDocument doc = new XmlDocument();
doc.Load("file_path.xml");
//add new data
XmlElement element = doc.CreateElement("NewElement");
element.InnerText = "test data";
doc.DocumentElement.AppendChild(element);
doc.Save("file_path.xml");
The ParseDaysXML routine is based on the ParseWeatherXML Routine. Not surprisingly, the code I copeid and pasted is working fine, but the stuff I tried to adapt isn't.
The commented code in ParseDaysXML is what is causing the problem. Based on the "Object reference not set to an instance of an object" error pointing to line 123 (second Dim line in the FindLayoutTable function), I'm suspecting something isn't right with my SelectSingleNode line (the first commented one).
So, three questions:
1) What is causing the error
2) how to fix?
3) My goal is simply to get period name from the WKKI2.xml file matched with the appopriate period in thew WKKI.xml file. Is there a more efficient way to go about it?
Private Structure WeatherTable
Public nodTimeLayout As XmlNode
Public nodData As XmlNode
End Structure
Private Structure WeatherData
Public wtHighTemp As WeatherTable
Public wtLowTemp As WeatherTable
Public wtLiquidPrecip As WeatherTable
Public wtSnowPrecip As WeatherTable
Public wtPrecipProb As WeatherTable
Public wtWindSpeed As WeatherTable
Public wtWindDirection As WeatherTable
Public wtCloudCover As WeatherTable
Public wtDayName As WeatherTable
Public wtNightName As WeatherTable
End Structure
Private Structure DayData
Public PeriodName As String
Public dt As Date
End Structure
Private Structure TemperatureData
Public F As Integer
Public ReadOnly Property C() As Integer
Get
Return Integer.Parse(Math.Round(((Double.Parse(F) - 32) / 9) * 5))
End Get
End Property
Public dt As Date
End Structure
Private Structure PrecipitationData
Public Inches As Double
Public ReadOnly Property MM() As Double
Get
Return Inches * 25.4
End Get
End Property
Public dt As Date
End Structure
Private Structure PercentData
Public Pct As Integer
Public dt As Date
End Structure
Private Structure WindData
Public Knots As Integer
Public ReadOnly Property MPH() As Integer
Get
Return Integer.Parse(Math.Round((Double.Parse(Knots) * 6076.12) / 5280))
End Get
End Property
Public Degrees As Integer
Public ReadOnly Property Dir() As String
Get
Select Case Degrees
Case 0 To 11.25, 348.75 To 360
Return "N"
Case 11.25 To 33.75
Return "NNE"
Case 33.75 To 56.25
Return "NE"
Case 56.25 To 78.75
Return "ENE"
Case 78.75 To 101.25
Return "E"
Case 101.25 To 123.75
Return "ESE"
Case 123.75 To 146.25
Return "SE"
Case 146.25 To 168.75
Return "SSE"
Case 168.75 To 191.25
Return "S"
Case 191.25 To 213.75
Return "SSW"
Case 213.75 To 236.25
Return "SW"
Case 236.25 To 258.75
Return "WSW"
Case 258.75 To 281.25
Return "W"
Case 281.25 To 303.75
Return "WNW"
Case 303.75 To 326.25
Return "NW"
Case 326.25 To 348.75
Return "NNW"
End Select
End Get
End Property
Public dt As Date
End Structure
Private Structure FormattedWeatherData
Public HighTemp() As TemperatureData
Public LowTemp() As TemperatureData
Public LiquidPrecip() As PrecipitationData
Public SnowPrecip() As PrecipitationData
Public PrecipProb() As PercentData
Public Wind() As WindData
Public CloudCover() As PercentData
Public DayName() As DayData
Public NightName() As DayData
End Structure
#End Region
#Region "NWS XML Reader http://www.nws.noaa.gov/forecasts/xml"
Private Function FindLayoutTable(ByVal xmlDoc As XmlDocument, ByVal nodData As XmlNode)
Dim nlTimeLayouts As XmlNodeList = xmlDoc.SelectNodes("/dwml/data/time-layout")
Dim strTimeLayout As String = nodData.Attributes("time-layout").Value
Dim node As XmlNode
For Each node In nlTimeLayouts
If strTimeLayout = node.SelectSingleNode("layout-key").InnerText Then
Return node
End If
Next
Return Nothing
End Function
Private Function ParseDateTime(ByVal str As String) As Date
Return Date.Parse(str.Replace("T", " ").Substring(0, str.LastIndexOf("-")))
End Function
Private Sub FillTemperatureData(ByVal wt As WeatherTable, ByRef temp() As TemperatureData)
Dim intCount As Integer
Dim nlData As XmlNodeList = wt.nodData.SelectNodes("value")
Dim nlDate As XmlNodeList = wt.nodTimeLayout.SelectNodes("start-valid-time")
For intCount = 0 To UBound(temp) - 1
temp(intCount) = New TemperatureData()
temp(intCount).F = Integer.Parse(nlData(intCount).InnerText)
temp(intCount).dt = ParseDateTime(nlDate(intCount).InnerText)
Next
End Sub
Private Sub FillPrecipitationData(ByVal wt As WeatherTable, ByRef precip() As PrecipitationData)
Dim intCount As Integer
Dim nlData As XmlNodeList = wt.nodData.SelectNodes("value")
Dim nlDate As XmlNodeList = wt.nodTimeLayout.SelectNodes("start-valid-time")
For intCount = 0 To UBound(precip) - 1
precip(intCount) = New PrecipitationData()
If Len(nlData(intCount).InnerText) = 0 Then
precip(intCount).Inches = 0
Else
precip(intCount).Inches = Double.Parse(nlData(intCount).InnerText)
End If
precip(intCount).dt = ParseDateTime(nlDate(intCount).InnerText)
Next
End Sub
Private Sub FillPercentData(ByVal wt As WeatherTable, ByRef pct() As PercentData)
Dim intCount As Integer
Dim nlData As XmlNodeList = wt.nodData.SelectNodes("value")
Dim nlDate As XmlNodeList = wt.nodTimeLayout.SelectNodes("start-valid-time")
For intCount = 0 To UBound(pct) - 1
pct(intCount) = New PercentData()
pct(intCount).Pct = Integer.Parse(nlData(intCount).InnerText)
pct(intCount).dt = ParseDateTime(nlDate(intCount).InnerText)
Next
End Sub
Private Sub FillWindData(ByVal wtSpeed As WeatherTable, ByVal wtDir As WeatherTable, ByRef wind() As WindData)
Dim intCount As Integer
Dim nlSpeed As XmlNodeList = wtSpeed.nodData.SelectNodes("value")
Dim nlDir As XmlNodeList = wtDir.nodData.SelectNodes("value")
Dim nlDate As XmlNodeList = wtSpeed.nodTimeLayout.SelectNodes("start-valid-time")
For intCount = 0 To UBound(wind) - 1
wind(intCount) = New WindData()
wind(intCount).Knots = Integer.Parse(nlSpeed(intCount).InnerText)
wind(intCount).Degrees = Integer.Parse(nlDir(intCount).InnerText)
wind(intCount).dt = ParseDateTime(nlDate(intCount).InnerText)
Next
End Sub
Private Sub FillDayData(ByVal wt As WeatherTable, ByRef DName() As DayData)
Dim intCount As Integer
Dim nlData As XmlNodeList = wt.nodData.SelectNodes("value")
Dim nlDate As XmlNodeList = wt.nodTimeLayout.SelectNodes("period-name")
For intCount = 0 To UBound(DName) - 1
DName(intCount) = New DayData()
DName(intCount).PeriodName = nlData(intCount).InnerText
DName(intCount).dt = ParseDateTime(nlDate(intCount).InnerText)
Next
End Sub
Private Function ParseForecastXML(ByVal strXMLWeather) As FormattedWeatherData
Try
'Setup variables
Dim xmlDoc As New XmlDocument()
Dim wdData As New WeatherData()
Dim fwdData As New FormattedWeatherData()
wdData.wtHighTemp = New WeatherTable()
wdData.wtLowTemp = New WeatherTable()
wdData.wtLiquidPrecip = New WeatherTable()
wdData.wtSnowPrecip = New WeatherTable()
wdData.wtPrecipProb = New WeatherTable()
wdData.wtWindSpeed = New WeatherTable()
wdData.wtWindDirection = New WeatherTable()
wdData.wtCloudCover = New WeatherTable()
'Load XML data
xmlDoc.Load(strXMLWeather)
'Load data and their corresponding time nodes
wdData.wtHighTemp.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/temperature[@type='maximum']")
wdData.wtLowTemp.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/temperature[@type='minimum']")
wdData.wtLiquidPrecip.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/precipitation[@type='liquid']")
wdData.wtSnowPrecip.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/precipitation[@type='snow']")
wdData.wtPrecipProb.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/probability-of-precipitation[@type='12 hour']")
wdData.wtWindSpeed.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/wind-speed[@type='sustained']")
wdData.wtWindDirection.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/direction[@type='wind']")
wdData.wtCloudCover.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/cloud-amount[@type='total']")
'Fill in data
FillTemperatureData(wdData.wtHighTemp, fwdData.HighTemp)
FillTemperatureData(wdData.wtLowTemp, fwdData.LowTemp)
FillPrecipitationData(wdData.wtLiquidPrecip, fwdData.LiquidPrecip)
FillPrecipitationData(wdData.wtSnowPrecip, fwdData.SnowPrecip)
FillPercentData(wdData.wtPrecipProb, fwdData.PrecipProb)
FillWindData(wdData.wtWindSpeed, wdData.wtWindDirection, fwdData.Wind)
FillPercentData(wdData.wtCloudCover, fwdData.CloudCover)
Return fwdData
Catch ex As Exception
MsgBox(ex.ToString)
Return Nothing
End Try
End Function
Private Function ParseDaysXML(ByVal strXMLWeather) As FormattedWeatherData
Try
'Setup variables
Dim xmlDaysDoc As New XmlDocument()
Dim wdDaysData As New WeatherData()
Dim fwdDaysData As New FormattedWeatherData()
'Load XML data
xmlDaysDoc.Load(strXMLWeather)
'Load data and their corresponding time nodes
'wdDaysData.wtDayName.nodData = xmlDaysDoc.SelectSingleNode("/dwml/data/time-layout/start-valid-time/@period-name")
'wdDaysData.wtNightName.nodData = xmlDaysDoc.SelectSingleNode("/dwml/data/time-layout/start-valid-time/@period-name")
wdDaysData.wtHighTemp.nodData = xmlDaysDoc.SelectSingleNode("/dwml/data/parameters/temperature[@type='maximum']")
wdDaysData.wtLowTemp.nodData = xmlDaysDoc.SelectSingleNode("/dwml/data/parameters/temperature[@type='minimum']")
'Fill in data
'FillDayData(wdDaysData.wtHighTemp, fwdDaysData.DayName)
'FillDayData(wdDaysData.wtLowTemp, fwdDaysData.NightName)
FillTemperatureData(wdDaysData.wtHighTemp, fwdDaysData.HighTemp)
FillTemperatureData(wdDaysData.wtLowTemp, fwdDaysData.LowTemp)
Return fwdDaysData
Catch ex As Exception
MsgBox(ex.ToString)
Return Nothing
End Try
End Function
#End Region
Private Sub btn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles btnWKKI.Click, btnKMAV.Click, btnWWWC.Click, btnKCHQ.Click
strStation = sender.Text
'load the weather array
Dim strWeatherXML As String = "http://distribution.customradionews.net/Forecast_XML/" & strStation & ".xml"
Dim fwdWeather As FormattedWeatherData = ParseForecastXML(strWeatherXML)
'load the days array
Dim strWeatherDaysXML As String = "http://distribution.customradionews.net/Forecast_XML/" & strStation & "2.xml"
Dim fwdWeatherDays As FormattedWeatherData = ParseDaysXML(strWeatherDaysXML)
Hi - Need help - some special characters are added to our XML document - unable to see this with notepad, wordpad, any type of XML readers like XMLSpy - is there a utility out there we could use? it adds this special characters at top of document ____ - the srainght line is the special characters.
thanks.
-- modified at 14:53 Friday 18th August, 2006
- Used Windiff - which displayed special characters.
- Removed the UTF-8 encoding - it seems to be causing error - leaving
- which seems to work for us.
<meaning>abc<type>xyz</type></meaning>
when i use
node.innertext
it concatenates abc and xyz both how can i retrive only the innertext of meaning tag.. i.e abc only
Please don't write URGENT in the title of your post. It's actually less likely to get answered that way.
To answer your question though, there are technically two child nodes of the <meaning> node. The first child is a text node, the second is the <type> element. Instead of using node.InnerText, get the first child node and get the InnerText of that: node.FirstChild.InnerText. You also will have to be careful about whitespace in these situations.
Logifusion[^]
If not entertaining, write your Congressman.
Input XML file: http://distribution.customradionews.net/Forecast_XML/WKKI.xml
Background: I'm working to interpret information from the National Weather Service's National Digital Forecast Database. There are a number places I've found that make use of the Web Srvice offered by the NWS for this data. For reasons of capacity, I am directly downloading the NDFD data and generating my own XML files. So, I end up with a series of xml files, 1 for each station we serve.
I want to parse that file into a string array, such that the forecast for each 12 hours is in one line. An example of what one data line should look like, using the file as it stands at 12:55pm CDT 8/17/06:
(Note: in order to get sample values for the conditions, I had to go to a day other than today in the raw data. Null values are acceptable in any of the fields after Temp)
I don't have any sample code, because I'm having a hard time wrapping my mind around how to get the data from one form to another. Why, I'm not sure. I have a feeling that once someone gets me started in the right direction, I'll be able to take it form there.
Not sure what you are asking for but here is how I interpret the XML.
All the "value" type elements (temperature, cloud-amount, weather) use a time-layout attribute to reference the [layout-key] element value that they map to. After you have the corrosponding parent element there is a one-to-one child element association.
I guess what I'm having difficulty wrapping my mind around is what type of loop I need to build to parse the code.
For instance, should I step through the period-names, using them to build element two of each record in the array, then step through the valid times, throwing them into element three, and so forth -- or should I execute 1 loop. I guess what's causing the disconnect for me is how I match (for instance) the third item in the "Daily Minimum Temperature" group with the third item in the second "time-layout" group, so I end up with a low for Saturday of 63 degrees.
I'm still enough of a noob that the code to make that matchup isn't clear to me. If someone can code a snippet that will make that matchup and output the strings "Satruday night" and "63", I'll be able to take it from there.
Thanks for your response...it helped me define the problem better, anyway1
Private Sub Button_Clicked(ByVal sender As Object, ByVal e As EventArgs) Handles btnWKKI.Click, btnWWWC.Click
Dim strStation As String = sender.Text
Dim xDocument As New XmlDocument()
xDocument.Load("http://distribution.customradionews.net/Forecast_XML/" & strStation & ".xml")
Dim xpPeriod As String = "//dwml/data/time-layout[2]/start-valid-time[3]/@period-name"
Dim xpTemp As String = "//dwml/data/parameters/temperature[2]/value[3]/text()"
Dim nTemp As XmlText = xDocument.SelectSingleNode(xpTemp)
Dim nPeriod As XmlAttribute = xDocument.SelectSingleNode(xpPeriod)
Dim nlPeriod As XmlNodeList = xDocument.SelectNodes("//dwml/data/time-layout[2]/start-valid-time/@period-name")
Dim nlTemp As XmlNodeList = xDocument.SelectNodes("//dwml/data/parameters/temperature[2]/value/text()")
Dim n As Integer = 0
While n < nlPeriod.Count
Console.WriteLine("{0} - {1}", (nlPeriod.Item(n) as XmlAttribute).Value, (nlTemp.Item(n) as XmlText).Value)
n += 1
End While
End Sub
However, the IDE gives "Expression Does Not Produce A Value" on Console.WriteLine("{0} - {1}", (nlPeriod.Item(n) as XmlAttribute)...the second part of the statement is okay. What did I miss?
I'm using an XPath statement ("XPath="gpx/trk/trkseg/trkpt") to bind all the trkpt elements to my data source. My goal is to return a page that displays all of the ELE data points, and numbers them according to their position in the XML file. It should read something like this:
ele = 85, position = 1
ele = 84, position = 2
ele = 82, position = 3
My DataList control correctly identifies all of the 'ele' elements using this syntax <%# XPath("ele") %>, however I have not be able to figure out how to find the position within my dataset. Using <%# XPath("position()") %> always returns 1, and everything else I have tried either returns the same number or throughs an exception. Can anyone clue me in as to what black magic is required to have XPath (I'm assuming its XPath) return its location within a series of identical elements?
There's nothing really black magic about it. The position() function really depends on context. It will return the position of the node currently being processed. It's hard to tell what you're doing from what's given. Can you post some of the code you're working on?
Logifusion[^]
If not entertaining, write your Congressman.
You can see this code being run here = http://www.loc8r.com/steve/test8.aspx
And you can see my XML file here = http://www.loc8r.com/steve/crashminus1.xml
I assumed that position() acted as you described, and if that were the case I'd suspect that the logic would be like this.
1. The ItemTemplate repeater class sets the context to the 1st TRKPT xml element. Position() should return 1.
2. The ItemTemplate repeater class increments the context to the 2nd TRKPT xml element. Position() should return 2.
3. The ItemTemplate repeater class increments the context to the 3rd TRKPT xml element. Position() should return 3.
As I mentioned position() is always returning "1", although "ele" is correctly displaying the 3 different values within the 3 different elements.
It's quite possible that position may not be at all effective when being used in this way. Take a look at this snippet:
string s = @"
<root>
<child>a</child>
<child>b</child>
<child>c</child>
</root>
";
XmlDocument doc = new XmlDocument();
doc.LoadXml(s);
XmlNodeList nl = doc.SelectNodes("//child");
foreach (XmlNode n in nl)
Console.WriteLine(n.CreateNavigator().Evaluate("position()"));
This will print out all 1's as well. I imagine that behind the scenes, a very similar process is happening to execute your XPath statements. So far, I have been unable to come up with an alternative XPath that will work. You may want to do this another way.
Logifusion[^]
If not entertaining, write your Congressman.
MSXML2::IXMLDOMDocument2Ptr pNewDocument;
pNewDocument.CreateInstance(__uuidof(MSXML2::DOMDocument));
//load the xml file
pNewDocument->load(_bstr_t("Infor.xml"));
MSXML2::IXMLDOMNodeListPtr pNodeList;
//get he sub node "Root/SubNode"
pNodeList = pNewDocument->selectNodes(_bstr_t("Root/SubNode"));
cout<<"The new Node length is "<<pNodeList->Getlength()<<endl;
With MSXML6, I change the "__uuidof(MSXML2::DOMDocument)" to "__uuidof(MSXML2::DOMDocument40)" or "__uuidof(MSXML2::DOMDocument60)". Then the codes above can't work.
I searched the help file os msxml6 and found that the GUIDS are related the version of MSXML. The table can be like this:
ProgID Version
MSXML2::DOMDocument msxml3.dll
MSXML2:: DOMDocument40 msxml4.dll
MSXML2::DOMDocument60 msxml6.dll
With MSXML6. Should I need to replace the "__uuidof(MSXML2::DOMDocument)" wihe "__uuidof(MSXML2::DOMDocument60)"?
All kinds of ways. Search for the node that is before or after the position you want to insert your new node and use InsertBefore or InsertAfter respectively on the parent node. That's if you have an XmlDocument object open. Another way is to just insert the node at the end and apply a stylesheet. The xsl:for-each can have a child element xsl:sort that can sort your nodes in alphabetical order.
Logifusion[^]
If not entertaining, write your Congressman.
Last Visit: 31-Dec-99 18:00 Last Update: 22-Sep-24 23:10