Adding data to node xml file in visual basic

I'm new to Visual Basic, so I want to excuse myself from the start.

The code below should get a list of nodes with all nodes, where InnerText of Name is equal to the string named membername . This part works fine, but then I also want to check if node Logout exists in this list. Thus, I want to prevent duplication of data in the xml database. Unfortunately, this does not work the way I tried. It copies all the data. So what is my mistake ??

XML FILE

 <?xml version="1.0" encoding="utf-16"?> <Times> <Shift> <Name>Philipp</Name> <Login>14:11</Login> <Date>25.03.2013</Date> <Logout>14:11</Logout> ' Don't generate again .... </Shift> <Shift> <Name>Philipp</Name> <Login>14:11</Login> <Date>25.03.2013</Date> <Logout>14:11</Logout> ' Generate Logout node </Shift> </Times> 

VISUAL BASIC CODE

  If File.Exists(Filename) Then DOMDocument.Load(Filename) Dim RootElement As XmlElement = DOMDocument.DocumentElement Dim ListOfTitles As XmlNodeList = DOMDocument.GetElementsByTagName("Name") For Each Node As XmlNode In ListOfTitles If Node.InnerText = memberName Then Dim logout = Node.SelectNodes("Logout") If Not logout Is Nothing Then Dim NewElement As XmlElement = DOMDocument.CreateElement("Logout") NewElement.InnerText = DateTime.Now.ToShortTimeString() Dim Parent As XmlNode = Node.ParentNode Parent.AppendChild(NewElement) DOMDocument.Save(Filename) End If End If Next End If 
+4
source share
3 answers

Try to explain what is wrong and how to solve it.

Apparently, for each <Name> node, you want to get the associated <Logout> node associated with it, if it exists, and you tried to execute Node.SelectNodes("Logout") , but:

The Node.SelectNodes("Logout") code is actually trying to select the child <Name> nodes represented by your Node variable, while in your XML markup

  • <Name> nodes have no children and

  • <Logout> nodes are always their siblings, not children.

Therefore, it always returns an empty collection, not a node.

You can solve this problem by going through your <Shift> nodes, as they contain name and exit information as child nodes.

By the way, InnerText not a property of IXMLDOMNode, try instead of Text

 If File.Exists(Filename) Then DOMDocument.Load(Filename) Dim RootElement As XmlElement = DOMDocument.DocumentElement Dim ListOfShifts As XmlNodeList = DOMDocument.GetElementsByTagName("Shift") For Each ShiftNode As XmlNode In ListOfShifts Dim NameNode = ShiftNode.SelectSingleNode("Name") If NameNode IsNot Nothing And NameNode.Text = memberName Then Dim logoutNode = ShiftNode.SelectSingleNode("Logout") If Not logoutNode Is Nothing Then Dim NewElement As XmlElement = DOMDocument.CreateElement("Logout") NewElement.Text = DateTime.Now.ToShortTimeString() Dim Parent As XmlNode = Node.ParentNode Parent.AppendChild(NewElement) DOMDocument.Save(Filename) End If End If Next End If 

In addition, you save the document every time you change it — why not save it only once after completing the cycle?

+2
source

logout set to an empty object, so If Not logout is Nothing Then equivalent to If True Then . See: http://msdn.microsoft.com/en-us/library/hcebdtae.aspx . The IXMLElement.selectNodes(expression) method always returns an object. To fix, check the length value for logout.

If logout.Count > 0 Then or use selectSingleNode , which returns NULL if no node is found.

+3
source

This is not exactly what you are asking for, but I believe that accessing raw XML leads to a lot of headache. Instead, you can simply consider the Shift class, which allows you to do the logic of your login / logout, as well as allow .NET to serialize / deserialize for you.

This way, you are not tied to specific XML paths if your business objects and relationships change.

Again, not what you asked for, but this is how I solve the business business you are dealing with.

First create a shift class into which I can put the business logic. A simple example is here:

 Public Class Shift Public Property Name As String Public Property DateString As String Public Property Login As String Public Property Logout As String End Class 

Then create a collection of shifts. I called this class TimeCollection, but I will call it whatever. Check it Serializable so that .NET can do the job of turning it from an object to XML and vice versa.

 Imports System Imports System.Collections.Generic Imports System.Linq Imports System.Text Imports System.IO Imports System.Xml.Serialization <Serializable()> Public Class TimeCollection Public Property Path As String <XmlArray("Shifts")> <XmlArrayItem(GetType(Shift))> Public Property Shift As Shift() Public Function Serialize(FileInfo As System.IO.FileInfo) Try If File.Exists(FileInfo.FullName) Then File.Delete(FileInfo.FullName) End If If Not Directory.Exists(FileInfo.DirectoryName) Then Directory.CreateDirectory(FileInfo.DirectoryName) End If Me.Path = FileInfo.FullName Dim serializer As XmlSerializer = New XmlSerializer(GetType(TimeCollection)) Dim writer As StreamWriter = New StreamWriter(FileInfo.FullName) serializer.Serialize(writer, Me) writer.Close() Catch ex As Exception Throw End Try End Function Public Shared Function Deserialize(FileInfo As FileInfo) As TimeCollection Dim serializedType As TimeCollection = Nothing Dim path As String = FileInfo.FullName If (Not File.Exists(path)) Then Deserialize = serializedType Else Try Dim serializer As XmlSerializer = New XmlSerializer(GetType(TimeCollection)) Dim reader As StreamReader = New StreamReader(path) serializedType = serializer.Deserialize(reader) reader.Close() Deserialize = serializedType Catch ex As Exception Console.WriteLine(ex.Message) End Try End If End Function End Class 

Now. If you have code that generates a series of shifts, for example:

  Dim tc As TimeCollection = New TimeCollection() Dim first As Shift = New Shift() first.Name = "Philipp" first.Login = "14:11" first.Logout = "14:45" first.DateString = "3/31/2013" Dim second As Shift = New Shift() second.Name = "Phillip" second.Login = "14:09" ' second.Logout = "15:01" (note 2nd shift has no logout) second.DateString = "4/1/2013" tc.Shift = New Shift(1) {first, second} 

You can easily serialize a TimeCollection object as follows:

 tc.Serialize(New FileInfo("C:\SomePath\TimeCollectionA.xml")) 

which creates the following content:

  <?xml version="1.0" encoding="utf-8"?> <TimeCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Path>C:\Temp\Tc.xml</Path> <Shifts> <Shift> <Name>Philipp</Name> <DateString>3/31/2013</DateString> <Login>14:11</Login> <Logout>14:45</Logout> </Shift> <Shift> <Name>Phillip</Name> <DateString>4/1/2013</DateString> <Login>14:09</Login> </Shift> </Shifts> </TimeCollection> 

Then, to deserialize the contents and return the file back to the collection of objects, you can do something with:

  Dim tc As TimeCollection tc = TimeCollection.Deserialize(New FileInfo("C:\SomePath\TimeCollectionA.xml")) 

Now you can iterate through the tc.Shift array, etc.

+1
source

All Articles