-
Jun 20th, 2016, 05:35 PM
#1
Thread Starter
New Member
Modify an attribute in an XML document and if not there create
Hello,
I have been grappling with XML attribute modification for the evening and have moderate success. I am, however, struggling with the modification of an attribute if it exists, or creating a new element for the child node if it does not exist with a new entry.
Here is the XML I am using as an example:-
Code:
<?xml version="1.0" encoding="utf-8"?>
<report>
<historic count="1110" starTime="2016-06-06T10:15:19.038Z" endTime="2012-08-24T10:15:19.038Z">
<daily>
<day date="2016-06-06" count="111"></day>
<day date="2016-06-07" count="222"></day>
<day date="2016-06-08" count="333"></day>
<day date="2016-06-09" count="444"></day>
</daily>
</historic>
<day>
<cars count="111" time="2016-06-06T10:15:12.038Z"></cars>
<cars count="222" time="2016-06-07T10:15:11.038Z"></cars>
<cars count="333" time="2016-06-08T10:15:10.038Z"></cars>
<cars count="444" time="2016-06-09T10:15:10.038Z">
<lane id="A" count="30"></lane>
<lane id="B" count="50"></lane>
<lane id="C" count="364"></lane>
</cars>
</day>
</report>
Here is the same XML with annotation to try and explain each section:-
Code:
<?xml version="1.0" encoding="utf-8"?>
<report>
** Count = the total count of all daily totals, ie: 111+222+333+444 = 1110
** startTime = when the file was first editted
** endTime = when the file was last editted
<historic count="1110" starTime="2016-06-06T10:15:19.038Z" endTime="2012-08-24T10:15:19.038Z">
<daily>
** Day totals
** If the current day is the 2016-06-09 then the 444 total would keep increasing as I wish, ie, adding +1, or +2 etc adhoc throughout the day
<day count="111" date="2016-06-06T10:15:12.038Z"></day>
<day count="222" date="2016-06-07T10:15:11.038Z"></day>
<day count="333" date="2016-06-08T10:15:10.038Z"></day>
<day count="444" date="2016-06-09T10:15:10.038Z"> </day>
</daily>
</historic>
<day>
** Day totals
<cars count="111" time="2016-06-06T10:15:12.038Z"></cars>
<lane id="A" count="0"></lane>
<lane id="B" count="111"></lane>
<lane id="C" count="0"></lane>
<cars count="222" time="2016-06-07T10:15:11.038Z"></cars>
<lane id="A" count="111"></lane>
<lane id="B" count="111"></lane>
<lane id="C" count="0"></lane>
<cars count="333" time="2016-06-08T10:15:10.038Z"></cars>
<lane id="A" count="111"></lane>
<lane id="B" count="111"></lane>
<lane id="C" count="111"></lane>
** Keep track of day total = 444 (30+50+364)
<cars count="444" time="2016-06-09T10:15:10.038Z">
** Keep track of each lane's total as well, so as /daily/cars/count increases but x amount, so does each lane ID and count as I pass data into it
<lane id="A" count="30"></lane>
<lane id="B" count="50"></lane>
<lane id="C" count="364"></lane>
</day>
</report>
How do I read the XML into VB.NET 2015 and modify an attribute and if the day's data does not exist, create it in report/daily and report/cars and then add the new attribute?
For example, how would I add one to the count attribute for the date "2016-06-06"?
and if it does not exist create a new day's data, such as:-
<day date="2017-06-06" count="1"></day>
Any pointers would be good - thank you
-
Jun 21st, 2016, 05:07 AM
#2
Re: Modify an attribute in an XML document and if not there create
Here are links to get you started.
How To Modify and Save XML with the XmlDocument Class in the .NET
Add attribute to an existing node
XmlNode.Attributes Property
Note: There are other choices out there such as LINQ to XML and other classes.
- kgc
-
Jun 21st, 2016, 06:37 AM
#3
Re: Modify an attribute in an XML document and if not there create
Here is some code using XElement that answers a little of what you asked. In the example I have used literal to represent the data but XElements can be loaded a variety of ways. The code is setup for you to be able to change one variable, dtmtch, and see how the code behaves. It should be enough code for you to learn how to do some of the other things you asked.
Code:
Dim foo As XElement 'hold EXAMPLE data
foo = <report>
<historic count="1110" starTime="2016-06-06T10:15:19.038Z" endTime="2012-08-24T10:15:19.038Z">
<daily>
<day date="2016-06-06" count="111"></day>
<day date="2016-06-07" count="222"></day>
<day date="2016-06-08" count="333"></day>
<day date="2016-06-09" count="444"></day>
</daily>
</historic>
<day>
<cars count="111" time="2016-06-06T10:15:12.038Z"></cars>
<cars count="222" time="2016-06-07T10:15:11.038Z"></cars>
<cars count="333" time="2016-06-08T10:15:10.038Z"></cars>
<cars count="444" time="2016-06-09T10:15:10.038Z">
<lane id="A" count="30"></lane>
<lane id="B" count="50"></lane>
<lane id="C" count="364"></lane>
</cars>
</day>
</report>
'run this using #6/9/2016# and DateTime.Now
Dim dtmtch As DateTime = #6/9/2016# ' DateTime.Now
Dim ie As IEnumerable(Of XElement) 'a place to store results from queries
'check for date match in historic daily
ie = From xe In foo.<historic>.<daily>.Elements
Where DateTime.Parse(xe.@date).Date = dtmtch.Date
Select xe Take 1
If ie.Count = 1 Then
'date matched
Dim ct As Integer = Integer.Parse(ie(0).@count) 'get current count
ct += 1
ie(0).@count = ct.ToString
Else
'no match
Dim proto As XElement = <day date=<%= DateTime.Now.ToString("yyyy-MM-dd") %> count="1"></day>
foo.<historic>.<daily>.LastOrDefault.Add(proto)
End If
'check for date match in day
ie = From xe In foo.<day>.Elements
Where DateTime.Parse(xe.@time).Date = dtmtch.Date
Select xe Take 1
'do we have <lane>
If ie.Count = 1 Then
For Each xe As XElement In ie(0).Elements
Stop
Next
Else
'no
End If
If you step through this you will see what is going on.
-
Jun 21st, 2016, 08:34 AM
#4
Thread Starter
New Member
Re: Modify an attribute in an XML document and if not there create
Thank you - very useful indeed. I will keep plodding on now
Last edited by johnali3n; Jun 21st, 2016 at 12:50 PM.
-
Jun 21st, 2016, 12:39 PM
#5
Thread Starter
New Member
Re: Modify an attribute in an XML document and if not there create
THis section doesn't seem to work? ie.Count is always 0 even if the element exists......I'll keep trying to debug but any ideas if I don't crack it?
Code:
'check for date match in historic daily
ie = From xe In foo.<historic>.<daily>.Elements
Where DateTime.Parse(xe.@date).Date = dtmtch.Date
Select xe Take 1
If ie.Count = 1 Then
'date matched
Dim ct As Integer = Integer.Parse(ie(0).@count) 'get current count
MsgBox(ct)
ct += 1
ie(0).@count = ct.ToString
MsgBox(ct)
Else
Last edited by johnali3n; Jun 21st, 2016 at 01:07 PM.
-
Jun 21st, 2016, 01:52 PM
#6
Re: Modify an attribute in an XML document and if not there create
You were supposed to change something in dbasnett's code. If you don't change it, it's possible for some data it will coincidentally work. But I think he intentionally set that variable to a value that's unlikely to do what you want.
Read his post again, he tells you which variable to change. Find that variable. It's set to a date that's not right now, and even has a comment suggesting what you should change it to. If you haven't done that, that's why it's not working.
If you have done that, I might take a crack at it, but his code looks functional, with the caveat it's omitting a lot of error handling in favor of 'being a clear tutorial'.
This answer is wrong. You should be using TableAdapter and Dictionaries instead.
-
Jun 21st, 2016, 02:43 PM
#7
Thread Starter
New Member
Re: Modify an attribute in an XML document and if not there create
Originally Posted by Sitten Spynne
You were supposed to change something in dbasnett's code. If you don't change it, it's possible for some data it will coincidentally work. But I think he intentionally set that variable to a value that's unlikely to do what you want.
Read his post again, he tells you which variable to change. Find that variable. It's set to a date that's not right now, and even has a comment suggesting what you should change it to. If you haven't done that, that's why it's not working.
If you have done that, I might take a crack at it, but his code looks functional, with the caveat it's omitting a lot of error handling in favor of 'being a clear tutorial'.
I did change that, yes. The program does create the new element if the data is not there for that day, or today, but if the element is already there, the number (count) for that day is not incremented. I
I have changed the code slightly (now loads and saves the XML as a file and some debugging plus a few lines where I thought the comparison on line "Where DateTime.Parse(xe.@date).Date = dtmtch.Date" wasn't quite right?):-
Code:
Imports System.Xml
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim foo As XElement = XElement.Load("data.xml") 'hold EXAMPLE data
'run this using #6/9/2016# and DateTime.Now
'Dim dtmtch As DateTime = #6/21/2016# ' DateTime.Now
Dim dtmtch As DateTime = DateTime.Now
'dtmtch = (Format(dtmtch, "yyyy-MM-dd"))
'MsgBox(Format(DateTime.Now, "yyyy-MM-dd"))
Dim ie As IEnumerable(Of XElement) 'a place to store results from queries
'check for date match in historic daily
ie = From xe In foo.<historic>.<daily>.Elements
Where DateTime.Parse(xe.@date).Date = dtmtch.Date
Select xe Take 1
MsgBox(ie.Count)
If ie.Count = 1 Then
'date matched
Dim ct As Integer = Integer.Parse(ie(0).@count) 'get current count
ct += 1
ie(0).@count = ct.ToString
MsgBox(ct)
Else
'no match
Dim proto As XElement = <day date=<%= DateTime.Now.ToString("yyyy-MM-dd") %> count="1"></day>
foo.<historic>.<daily>.LastOrDefault.Add(proto)
End If
'check for date match in day
ie = From xe In foo.<day>.Elements
Where DateTime.Parse(xe.@time).Date = dtmtch.Date
Select xe Take 1
'do we have <lane>
If ie.Count = 1 Then
For Each xe As XElement In ie(0).Elements
Stop
Next
Else
'no
End If
foo.Save("data-save.xml")
Close()
End Sub
End Class
-
Jun 21st, 2016, 02:47 PM
#8
Thread Starter
New Member
Re: Modify an attribute in an XML document and if not there create
The problem of adding +1 (or whatever) to the count attribute seems to lie where the element exists for the day specific and is able to increment one to the count successfully but if the day already exists when the program is run, then the count for that day is not incremented by one. I think it is because of this comparison below, but I am not sure - ie.count is never greater than 0 if the element for the day specified exists unless it is the first element in that part of the XML:-
Code:
'check for date match in historic daily
ie = From xe In foo.<historic>.<daily>.Elements
Where DateTime.Parse(xe.@date).Date = dtmtch.Date
Select xe Take 1
So, as there is no match, the element is recreated each time but with 1 instead of an incremented count:-
Code:
If ie.Count = 1 Then
'date matched
Dim ct As Integer = Integer.Parse(ie(0).@count) 'get current count
ct += 1
ie(0).@count = ct.ToString
MsgBox("match")
Else
'no match
Dim proto As XElement = <day date=<%= DateTime.Now.ToString("yyyy-MM-dd") %> count="1"></day>
foo.<historic>.<daily>.LastOrDefault.Add(proto)
MsgBox("Not match")
End If
"Not match" is always displayed in the message box as debug.
Last edited by johnali3n; Jun 21st, 2016 at 03:58 PM.
-
Jun 21st, 2016, 06:25 PM
#9
Re: Modify an attribute in an XML document and if not there create
Originally Posted by johnali3n
I have changed the code slightly (now loads and saves the XML as a file and some debugging plus a few lines where I thought the comparison on line "Where DateTime.Parse(xe.@date).Date = dtmtch.Date" wasn't quite right?):-
Code:
'
Dim foo As XElement = XElement.Load("data.xml") 'hold EXAMPLE data
'hmmmmmm - lines deleted
foo.Save("data-save.xml")
'
Does this help you understand what the problem is?
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
|