Results 1 to 9 of 9

Thread: Modify an attribute in an XML document and if not there create

  1. #1

    Thread Starter
    New Member
    Join Date
    Sep 2008
    Posts
    11

    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

  2. #2
    Frenzied Member KGComputers's Avatar
    Join Date
    Dec 2005
    Location
    Cebu, PH
    Posts
    2,020

    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
    CodeBank: VB.NET & C#.NET | ASP.NET
    Programming: C# | VB.NET
    Blogs: Personal | Programming
    Projects: GitHub | jsFiddle
    ___________________________________________________________________________________

    Rating someone's post is a way of saying Thanks...

  3. #3
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    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.
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

  4. #4

    Thread Starter
    New Member
    Join Date
    Sep 2008
    Posts
    11

    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.

  5. #5

    Thread Starter
    New Member
    Join Date
    Sep 2008
    Posts
    11

    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.

  6. #6
    You don't want to know.
    Join Date
    Aug 2010
    Posts
    4,578

    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.

  7. #7

    Thread Starter
    New Member
    Join Date
    Sep 2008
    Posts
    11

    Re: Modify an attribute in an XML document and if not there create

    Quote Originally Posted by Sitten Spynne View Post
    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

  8. #8

    Thread Starter
    New Member
    Join Date
    Sep 2008
    Posts
    11

    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.

  9. #9
    Powered By Medtronic dbasnett's Avatar
    Join Date
    Dec 2007
    Location
    Jefferson City, MO
    Posts
    9,754

    Re: Modify an attribute in an XML document and if not there create

    Quote Originally Posted by johnali3n View Post
    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?
    My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
    Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

    "Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein

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
  •  



Click Here to Expand Forum to Full Width