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.