0 Replies - 5112 Views - Last Post: 03 August 2011 - 04:58 AM Rate Topic: -----

#1 MadeToFail  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 20-June 11

Deleting first node in the DocumentElement in an XML file

Posted 03 August 2011 - 04:58 AM

Hello everyone. I'm trying to delete the first node in the document element. However, it keeps giving an ArgumentException ("The oldChild is not a child of this node. Or this node is read-only.")
This is the class I'm using:
Imports System.Xml
Imports System.IO

''' <summary>
''' An XML object
''' </summary>
Public Class Xml
    ''' <summary>
    ''' The filename
    ''' </summary>
    Dim f As String

    ''' <summary>
    ''' The XmlDocument object
    ''' </summary>
    Dim xd As XmlDocument = Nothing

    ''' <summary>
    ''' The start element
    ''' </summary>
    Dim SElement As String

    ''' <summary>
    ''' Creates an XML object
    ''' </summary>
    ''' <param name="fileName">The name of the XML file</param>
    ''' <param name="StartElement">The name of the element that needs to be created if the file doesn't exist</param>
    Public Sub New(ByVal fileName As String, ByVal StartElement As String, Optional ByVal ReCreate As Boolean = False)
        f = fileName
        SElement = StartElement

        If (Not File.Exists(fileName)) Or (ReCreate) Then
            Dim w As XmlTextWriter = New XmlTextWriter(f, System.Text.Encoding.UTF8)
            w.WriteStartDocument(True)
            w.Formatting = Formatting.Indented
            w.Indentation = 2
            w.WriteStartElement(StartElement)
            ' Don't write anything (except the startelement) just to create it
            w.WriteEndElement()
            w.WriteEndDocument()
            w.Close()
        End If

        xd = New XmlDocument()
        xd.Load(f)
    End Sub

    ''' <summary>
    ''' Creates a node in the XML file
    ''' </summary>
    ''' <param name="nodeStartElement">The main node name</param>
    ''' <param name="nodeData">The data that needs to be written into the node; is a Collection with the class "SColl"</param>
    ''' <param name="maxNodes">The number of max nodes that are allowed; -1 to disable</param>
    Public Sub CreateNode(ByVal nodeStartElement As String, ByVal nodeStartElementAttributes As String, ByVal nodeData As Collection, Optional ByVal maxNodes As Short = -1)
        Dim newNode As String = vbCrLf
        newNode &= "  <" & nodeStartElement
        If (nodeStartElementAttributes <> String.Empty) Then
            newNode &= " " & nodeStartElementAttributes
        End If
        newNode &= ">" & vbCrLf

        Dim i As Integer = 0
        For Each el As SColl In nodeData
            newNode &= "    <" & CStr(el.a) & ">" & (el.b.ToString().Replace("<", "&gt;").Replace(">", "&lt;")) & "</" & CStr(el.a) & ">" & vbCrLf
            i += 1
        Next el

        newNode &= "  </" & nodeStartElement & ">" & vbCrLf

        Dim docFrag As XmlDocumentFragment = xd.CreateDocumentFragment()
        docFrag.InnerXml = newNode
        Dim root As XmlNode = xd.DocumentElement
        root.AppendChild(docFrag)

        If (maxNodes > -1) Then
            Dim nodeCount As Integer = 0
            Try
                nodeCount = CInt(xd.DocumentElement.ChildNodes.Count / nodeData.Count())
            Catch ' In case there are 0 nodes that were added, it will give a 'divide by zero' error
            End Try
            While (nodeCount > maxNodes)
                xd.RemoveChild(xd.DocumentElement.FirstChild)
                nodeCount -= 1
            End While
        End If
    End Sub

    ''' <summary>
    ''' Reads the nodes inside nodeStartElement
    ''' </summary>
    ''' <param name="nodeStartElement">The node where it has to be searched in</param>
    ''' <returns>A collection with all the data in it</returns>
    Public Function ReadNodes(ByVal nodeStartElement As String) As Collection
        Dim xmldoc As New XmlDataDocument()
        Dim xmlnode As XmlNodeList
        Dim fs As FileStream = New FileStream(f, FileMode.Open, FileAccess.Read)
        xmldoc.Load(fs)
        xmlnode = xmldoc.GetElementsByTagName(nodeStartElement)

        Dim theNode As XmlNode = xmlnode(0)
        Dim theColl As Collection = New Collection
        Dim nColl As New Collection

        For Each el As XmlNode In theNode.ChildNodes
            nColl = New Collection
            For Each ela As XmlNode In el.ChildNodes
                nColl.Add(New SColl(ela.Name, ela.InnerText))
            Next ela
            theColl.Add(nColl)
        Next el

        fs.Close()
        Return theColl
    End Function

    ''' <summary>
    ''' Saves the file
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Close()
        xd.Save(f)
    End Sub
End Class

Public Class SColl
    Public a As Object
    Public b As Object

    Public Sub New(ByVal ElA As Object, ByVal ElB As Object)
        a = ElA
        b = ElB
    End Sub
End Class


(I know there are better ways to do such things, and if you know one, you can tell me...)

And this is how I call the class etc.:
    Sub Main()
        Console.WriteLine("Attempting to write...")
        Console.WriteLine("-------------")

        Dim Time1 As Integer = DateTime.Now.Millisecond
        Dim x As Xml = New Xml("test.xml", "ChatMessages", True)
        ' First write some things in the file
        Dim cl As New Collection
        cl.Add(New SColl("User", "User1"))
        cl.Add(New SColl("Text", "Gz with winning! ;)/>"))
        cl.Add(New SColl("Time", "14:12:14"))
        x.CreateNode("Message", "id='" & lastCID & "'", cl, 5)
        lastCID += 1

        cl = New Collection
        cl.Add(New SColl("User", "User2"))
        cl.Add(New SColl("Text", "Yay! Thankzzz. :3"))
        cl.Add(New SColl("Time", "14:12:26"))
        x.CreateNode("Message", "id='" & lastCID & "'", cl, 5)
        lastCID += 1

        cl = New Collection
        cl.Add(New SColl("User", "User1"))
        cl.Add(New SColl("Text", "Np dude! ^^/>"))
        cl.Add(New SColl("Time", "14:12:35"))
        x.CreateNode("Message", "id='" & lastCID & "'", cl, 5)
        lastCID += 1

        cl = New Collection
        cl.Add(New SColl("User", "User3"))
        cl.Add(New SColl("Text", "Gz too!"))
        cl.Add(New SColl("Time", "14:12:36"))
        x.CreateNode("Message", "id='" & lastCID & "'", cl, 5)
        lastCID += 1

        cl = New Collection
        cl.Add(New SColl("User", "User1"))
        cl.Add(New SColl("Text", "Ty dudes! ^^/>"))
        cl.Add(New SColl("Time", "14:12:43"))
        x.CreateNode("Message", "id='" & lastCID & "'", cl, 5)
        lastCID += 1

        cl = New Collection
        cl.Add(New SColl("User", "User3"))
        cl.Add(New SColl("Text", "Np... :D/>"))
        cl.Add(New SColl("Time", "14:12:49"))
        x.CreateNode("Message", "id='" & lastCID & "'", cl, 5)
        lastCID += 1

        cl = New Collection
        cl.Add(New SColl("User", "User2"))
        cl.Add(New SColl("Text", "Np again xD"))
        cl.Add(New SColl("Time", "14:12:49"))
        x.CreateNode("Message", "id='" & lastCID & "'", cl, 5)
        lastCID += 1

        x.Close()
        Dim Time2 As Integer = DateTime.Now.Millisecond

        Console.WriteLine("Done writing.")
        Console.WriteLine("Attempting to read...")
        Console.WriteLine("-------------")

        Dim Time3 As Integer = DateTime.Now.Millisecond
        Dim a As Collection = x.ReadNodes("ChatMessages")
        Dim nColl As Collection
        For Each el As Collection In a
            nColl = New Collection
            For Each ela As SColl In el
                nColl.Add(ela.b, ela.a)
            Next ela
            Console.WriteLine("[" & nColl("Time") & "] " & nColl("User") & ": " & nColl("Text"))
        Next el
        Dim Time4 As Integer = DateTime.Now.Millisecond

        Console.WriteLine("-------------")
        Console.WriteLine("Done reading.")
        Console.WriteLine("Total execution time: " & (Time4 - Time1) & " ms:")
        Console.WriteLine("- Writing: " & (Time2 - Time1) & " ms")
        Console.WriteLine("- Reading: " & (Time4 - Time3) & " ms")
        If (Console.ReadLine().ToLower() = "a") Then ' Again
            Console.Clear()
            Main()
        End If
    End Sub



The problem is line 82 of the Xml class. So when I add a 6th chat message (and the limit is set to 5), I get the ArgumentException at line 82 of the Xml class.
If you know better ways to do such things, you are surely welcome to say them (or show them of course).
Feel free to ask questions about my code, since it seems a bit messy.

Thanks in advance!
--
MadeToFail

This post has been edited by MadeToFail: 03 August 2011 - 05:03 AM


Is This A Good Question/Topic? 0
  • +

Page 1 of 1