4

私はVisualBasicを初めて使用するので、最初から言い訳をしたいと思います。

InnerText以下のコードは、 ofが。Nameという名前の文字列と等しいすべてのノードを含むノードリストを取得することになっていますmembernameLogoutこの部分は完全に機能しているようですが、後でこのリストにノードがすでに存在するかどうかも確認したいと思います。このようにして、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>

ビジュアルベーシックコード

   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

3 に答える 3

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

于 2013-03-25T17:07:39.113 に答える
2

何が悪いのか、そしてそれをどのように解決するのかを説明してみましょう。

どうやら、ノードごとに、それに関連付けられているノードが存在する場合はそれ<Name>を取得したいのですが、これを実行しようとしましたが、次のようになります。<Logout>Node.SelectNodes("Logout")

コードNode.SelectNodes("Logout")は実際には、変数で表されるノードのノードを選択しようとします-XMLマークアップ中に、<Name>Node

  1. <Name>ノードには子がなく、

  2. <Logout>ノードは常に兄弟であり、子ではありません。

したがって、必要なノードではなく、常に空のコレクションを返します。

<Shift>ノードには名前とログアウトの両方の情報が子ノードとして含まれているため、ノードを反復処理することでこれを解決できます。

ちなみに、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

また、変更のたびにドキュメントを保存しています-ループが終了した後に一度だけ保存してみませんか

于 2013-04-02T23:17:50.017 に答える
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と呼びましたが、好きなように呼んでください。.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配列などを反復処理できます。

于 2013-03-30T22:36:20.953 に答える