2013-03-25 63 views
4

我對Visual Basic來說很新,所以我想從一開始就讓自己諒解。將數據添加到Visual Basic中的xml文件的節點

下面的代碼應該得到一個節點列表,其中InnerTextInnerText等於名爲membername的字符串。這部分似乎很完美,但之後我還想檢查在此列表中是否已存在節點Logout。這樣我想防止重複XML數據庫中的數據。不幸的是,它不能像我嘗試過的那樣工作。它不斷複製所有的數據。那麼,我的錯誤是什麼?

XML文件

<?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代碼

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 
+0

我將標記從「vb6」更改爲「vb.net」。 – 2013-03-29 00:46:48

+0

我對GojiraDeMonstah的回答+1了。如果還不算太晚,如果只有不到1000行的代碼執行此XML Run,RUN,RUNNNN的速度可以儘可能快地遠離直接操作XML並使用對象運行TO。我無法強調能夠以1/3的錯誤快速編寫3x的精彩程度。我可以說,相信我,你會喜歡它的。 – FastAl 2013-04-02 20:12:43

+0

我錯了,還是'InnerText'應該只是'Text' – Luc125 2013-04-02 23:22:08

回答

2

讓我們試着解釋什麼是錯的,以及如何解決它。

顯然你願意,每個<Name>節點,檢索與此相關的<Logout>節點,如果它存在,你試過Node.SelectNodes("Logout")要做到這一點,但:

代碼Node.SelectNodes("Logout")實際嘗試選擇孩子<Name>節點的節點表示您Node變量 - 而在你的XML標記,

  1. <Name>節點沒有孩子,

  2. <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 

此外,您節省每一個變化的文件 - 爲什麼不救它只有一次循環完成後

3

logout被設置爲一個空的對象,因此If Not logout is Nothing Then相當於If True Then。請參閱:http://msdn.microsoft.com/en-us/library/hcebdtae.aspx。方法IXMLElement.selectNodes(expression)總是返回一個對象。要修復,請檢查註銷的長度值。如果找不到節點,則返回NULL

+0

可否請您加一些更詳細的代碼? logout.length不起作用。我試着用chooseinglenode來使用它。你的鏈接指向一個c#和C++鏈接。 – 2013-03-25 21:28:24

+0

@PhilippBraun該鏈接指的是MS XML(不可否認的是WinCE版本),這是你在VB6中使用的。大多數MSDN文檔都是用C++編寫的。 – Deanna 2013-03-26 10:37:14

+0

坦克,但我仍然沒有得到如何在這裏使用.length。 – 2013-03-26 12:33:25

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數組等等

+0

好戲,爵士! – 2013-04-03 08:16:05