我是Visual Basic的新手,所以我想从一开始就原谅自己。
下面的代码应该得到一个节点列表,其中InnerText
的{{1}}等于名为Name
的字符串。这部分似乎工作得很好,但之后我还要检查在此列表中是否已存在节点membername
。这样我想防止重复xml数据库中的数据。不幸的是,它不像我尝试的那样工作。它不断复制所有数据。那我的错是什么?
XML文件
Logout
VISUAL BASIC CODE
<?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>
答案 0 :(得分:3)
logout
被设置为空对象,因此If Not logout is Nothing Then
等同于If True Then
。见:http://msdn.microsoft.com/en-us/library/hcebdtae.aspx。方法IXMLElement.selectNodes(expression)
始终返回一个对象。要修复,请检查注销的长度值。
If logout.Count > 0 Then
或使用selectSingleNode
,如果找不到节点则返回NULL
。
答案 1 :(得分:2)
让我们试着解释什么是错的,以及如何解决它。
显然,您希望每个<Name>
节点检索与其关联的<Logout>
节点(如果存在),并且您尝试Node.SelectNodes("Logout")
执行此操作,但是:
在您的XML标记中,代码Node.SelectNodes("Logout")
实际上会尝试选择<Name>
变量所代表的Node
节点的子节点,
<Name>
个节点没有子节点
<Logout>
节点总是他们的兄弟姐妹,而不是孩子。
所以它总是返回一个空集合,而不是你想要的节点。
您可以通过遍历<Shift>
节点来解决此问题,因为它们包含Name和Logout信息作为子节点。
顺便说一下,InnerText
不是IXMLDOMNode属性,请尝试使用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
此外,您将在每次更改时保存文档 - 为什么不在循环完成后仅保存一次
答案 2 :(得分:1)
这不完全是你所要求的,但我发现处理原始XML会导致很多麻烦。您可能会考虑的是只处理一个Shift类,它允许您在登录/注销时执行逻辑,并让.NET为您执行序列化/反序列化。
这样,如果业务对象和关系发生变化,您就不会受特定XML路径的约束。
同样,不是你问的问题,但这里是我如何解决你正在处理的商业案例。
首先,创建一个我可以将业务逻辑放入的移位类。这里的简单示例:
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
接下来,创建一个班次集合。我把这个类称为TimeCollection,但是无论你想要什么,都可以调用它。将其标记为Serializable,以便.NET可以将其从对象转换为XML,反之亦然。
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
现在。如果你有一些代码产生一系列的转变,如下所示:
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}
您可以像这样轻松地序列化TimeCollection对象:
tc.Serialize(New FileInfo("C:\SomePath\TimeCollectionA.xml"))
创建以下内容:
<?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>
然后,要反序列化内容并将文件转回到对象集合中,您可以执行以下操作:
Dim tc As TimeCollection
tc = TimeCollection.Deserialize(New FileInfo("C:\SomePath\TimeCollectionA.xml"))
现在你可以遍历tc.Shift数组等。