код удаляет только первый набор xml-узлов, а не другие

#xml #vb.net

#xml #vb.net

Вопрос:

У меня возникли некоторые проблемы с моим кодом. когда я запускаю его, он удаляет только первый набор xml-узлов. Если я попытаюсь удалить второй или третий, ничего не будет удалено. Я также читаю в XML-файле. Я не думаю, что мой код выполняется должным образом. Я хочу, чтобы мой код перебирал все дочерние узлы и удалял тот, который введен в текстовом поле.Кто-нибудь знает причину, по которой это могло произойти.

 Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click

    Dim doc As New XmlDocument()
    doc.Load(path amp; FileXml)
    Dim Nodes = doc.SelectNodes("//TicketNumber")
    For Each elem As XmlElement In Nodes
        Console.WriteLine(elem.InnerText)

        If elem.InnerText = TextBox1.Text Then
            elem.ParentNode.ParentNode.RemoveChild(elem.ParentNode)
            MessageBox.Show("Element Deleted! ") 'amp; TicketNumber.ToString)           
            Exit For
        End If
    Next
    doc.Save(path amp; FileXml)
End Sub
  

пример xml-кода: (примечание: у меня могут быть сотни строк xml)

  <?xml version="1.0" encoding="us-ascii" standalone="yes"?>
<sales_audit_xml>
  <DataTable>
    <TicketNumber>0145191647504</TicketNumber>
    <Total_Amt>11.39</Total_Amt>
    <Total_Taxes>0.00</Total_Taxes>  
    <Code>SUN1</Code>  
  </DataTable>
  <DataTable>
    <TicketNumber>0145191647505</TicketNumber>
     <Total_Amt>11.39</Total_Amt>
    <Total_Taxes>0.00</Total_Taxes>  
    <Code>SUN1</Code>
  </DataTable>
  <DataTable>
     <TicketNumber>0145192428666</TicketNumber>
     <Total_Amt>13.64</Total_Amt>
    <Total_Taxes>0.00</Total_Taxes>  
    <Code>SUN1</Code>  
  </DataTable>
</sales_audit_xml>
  

полный код

 Imports System.Xml
Imports System.Text
Imports System.IO
Imports System.Xml.Schema
Imports System.Xml.XPath
Imports System.Text.RegularExpressions

Public Class Form1
    Dim Filetxt As String = "textfile.txt"
    Dim path As String = "filepath"
    Dim FileXml As String = "xmlfile.xml"
    Dim FileXsd As String = "schema.xsd"
    Dim RootEle As String = "sales_audit_xml"
    Dim FirstEle As String = "DataTable"
    Dim lstErrs As New List(Of String)
    Dim strFilNme As String = Me.txtFilNme.Text

    '-----Read in txt file and convert to xml file
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim myText As String = My.Computer.FileSystem.ReadAllText(path amp; Filetxt)
        Dim ary As String() = myText.Split(vbCrLf)
        Dim writer As New XmlTextWriter(path amp; FileXml, Encoding.ASCII)
        writer.Formatting = Formatting.Indented
        writer.Indentation = 4
        writer.WriteStartDocument(True)
        writer.WriteStartElement(RootEle)
        ' data for each element in the array
        For x As Integer = 0 To ary.Length - 1
            Writestudent(writer, ary(x))
        Next
        writer.WriteEndElement()
        writer.WriteEndDocument()
        writer.Close()
    End Sub
    Private Sub Writestudent(ByVal wr As XmlWriter, ByVal str As String)

        Dim ary As String() = str.Split(strDelimiter)

        wr.WriteStartElement("DataTable")
        wr.WriteStartElement("TicketNumber")
        wr.WriteString(ary(0))
        wr.WriteEndElement()
        wr.WriteStartElement("Total_Amt")
        wr.WriteString(ary(1))
        wr.WriteEndElement()
        wr.WriteStartElement("Total_Taxes")
        wr.WriteString(ary(2))
        wr.WriteEndElement()
        wr.WriteStartElement("code")
        wr.WriteString(ary(3))
        wr.WriteEndElement()
        wr.WriteEndElement()

    End Sub

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    '--read file
        Dim reader As XmlReader = Nothing
        Dim fileWriter As IO.StreamWriter = Nothing
        Dim fileInfo As IO.FileInfo = Nothing
        Dim fileWrite As IO.StreamWriter = Nothing

        Dim TicketNumber As String = Nothing
        Dim Total_Amt As String = Nothing
        Dim Total_Taxes As String = Nothing
        Dim code As String = Nothing

    Try

        fileInfo = New IO.FileInfo(strFilNme)

        'create a file in directory and write (errors) to that file
        fileWriter = New IO.StreamWriter(fileInfo.DirectoryName amp; "ErrorMessages.txt")

        Dim settings As XmlReaderSettings = New XmlReaderSettings()
        settings.Schemas.Add("namespace", path amp; FileXsd)
        settings.ValidationType = ValidationType.Schema

        reader = XmlReader.Create(txtFilNme.Text, settings)
        Dim document As XmlDocument = New XmlDocument()

        document.Load(reader)

        'validate xml
        Dim eventHandler As ValidationEventHandler = New ValidationEventHandler(AddressOf ValidationEventHandler)
        ' the following call to Validate succeeds.
        document.Validate(eventHandler)
        'add a node so that the document Is no longer valid
        Dim navigator As XPathNavigator = document.CreateNavigator()
        navigator.MoveToFollowing("Difference", "namespace")

        document.Validate(eventHandler)

        reader.Close()


        Dim xdoc As XmlDocument
        Dim nodelist As XmlNodeList

        xdoc = New XmlDocument
        Dim xmlData As String = path amp; FileXml
        xdoc.Load(xmlData)
        nodelist = xdoc.GetElementsByTagName("DataTable")

        Dim intNdeCnt As Integer = 0
        Dim lstNodeErrs As New List(Of String)

        For Each node1 As XmlElement In nodelist

            '-- Counter
            intNdeCnt  = 1

            lstNodeErrs.Add("------ Checking node: " amp; intNdeCnt)

            TicketNumber = node1("TicketNumber").InnerText.Trim
            Total_Amt = node1("Total_Amt").InnerText.Trim
            Total_Taxes = node1("Total_Taxes").InnerText.Trim
            code = node1("code").InnerText
        Next
        If lstErrs.Count > 0 Then


            MsgBox("Complete but with errors! Check error file.") 'amp; vbCrLf amp; vbCrLf amp; Strings.Join(lstErrs.ToArray, vbCrLf))
            fileWriter.WriteLine("Filename:   " amp; strFilNme)
            fileWriter.WriteLine(vbCrLf)
            fileWriter.WriteLine("Errors:")
            For i As Integer = 0 To lstErrs.Count - 1
                fileWriter.WriteLine(lstErrs(i))
            Next

        Else
            MsgBox("Complete!")
            Exit Sub
        End If

        fileWriter.Close()

    Catch ex As XmlSchemaValidationException
        MsgBox("Complete but with errors! Check error file.")
        fileWriter.WriteLine("[Error]: XmlSchemaValidationException -error!!!!!!")
        fileWriter.WriteLine("LineNumber = {0}", ex.LineNumber)
        fileWriter.WriteLine("LinePosition = {0}", ex.LinePosition)
        fileWriter.WriteLine("Message = {0}", ex.Message)
        fileWriter.WriteLine("Source = {0}", ex.Source)

    Catch exOther As Exception
        MsgBox("Complete but with errors! Check error file.")
        fileWriter.WriteLine("[Error]: " amp; exOther.Message amp; exOther.StackTrace)

    Finally

        If Not IsNothing(reader) Then
            reader.Close()
        End If

        If Not IsNothing(fileWriter) Then
            fileWriter.Close()
        End If

    End Try
End Sub

Private Sub ValidationEventHandler(ByVal sender As Object, ByVal e As ValidationEventArgs)

    'MsgBox("Display Errors")
    Select Case e.Severity
        Case XmlSeverityType.Error
            lstErrs.Add("Error: {0} " amp; e.Message)
        Case XmlSeverityType.Warning
            lstErrs.Add("Warning {0} " amp; e.Message)
        Case Else
            lstErrs.Add(e.Message)

    End Select
End Sub

Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click

    Dim doc As New XmlDocument()
    doc.Load(path amp; FileXml)
    Dim Nodes = doc.SelectNodes("//TicketNumber")
    For Each elem As XmlElement In Nodes

        If elem.InnerText = TextBox1.Text Then
            elem.ParentNode.ParentNode.RemoveChild(elem.ParentNode)
            MessageBox.Show("Element Deleted! ") 'amp; TicketNumber.ToString)           

        End If
    Next
    doc.Save(path amp; FileXml)
End Sub
  

Конечный класс

первая кнопка предназначена для чтения в текстовом файле, вторая для средства проверки схемы и третья для удаления элементов. У меня также есть текстовое поле для удаления номера билета

Комментарии:

1. Ваша строка Exit For , гарантирует, что цикл завершится, как только вы найдете первый соответствующий элемент. Что вы подразумеваете под «попыткой удалить второй или третий»? Вы нажимаете Button5 несколько раз (например, кнопку «Далее»)?

2. если я запущу свой код и решу, что хочу удалить номер билета 0145191647505 (на который я ссылался как на второй набор XML-данных), он не будет удален. Однако, если я добавлю номер билета 0145191647504 (первый набор XML-данных), он отлично работает. Если я вставлю или выну exit for, у меня все еще будет та же проблема.

3. Поставьте точку останова в строке For Each elem As XmlElement In Nodes . Для вашего второго набора XML-данных посмотрите, сколько элементов в Nodes . Шаг-отладка-в ваш цикл и наведите указатель мыши на значения, чтобы увидеть, имеет ли каждое elem соответствующее значение.

4. имеется правильное количество узлов. когда я ставлю точку останова в If elem. innerText = TextBox1.Text Затем я получаю 0145191647504 при наведении курсора мыши на innerText и 0145191647505 при наведении курсора мыши на TextBox1. Я также ввел «Консоль. Строка записи (элемент. innerText)» после строки для каждого элемента как XmlElement в Nodes, и в нем перечислены все правильные узлы на консоли

5. Вы получаете окно сообщения «Элемент удален!» для каждого узла тоже?

Ответ №1:

Лично я предпочитаю использовать класс XDocument, который был реализован в .Net 3.5.

Учитывая, что:

  • Ваша структура XML всегда одинакова
  • Вы используете .Net 3.5 или новее

Я закодировал что-то вроде этого, чтобы удалять только строку, которую я выбираю, со строкой «deleteme», которая может быть вашим «TextBox1.Text».

Когда я писал это, он удалял бы каждый, содержащий данную строку. Если вы уверены, что у вас есть только одна запись с заданной строкой, вы можете ввести команду «Exit For», как вы делали в своем примере.

     Dim tst_xml_path = "MyPath"
    Dim deleteme As String = ("0145191647505")
    Dim doc As New XDocument()


    doc = XDocument.Load(tst_xml_path amp; "tst.xml")
    For Each elem In doc.<sales_audit_xml>.<DataTable>
        If elem.<TicketNumber>.Value = deleteme Then
            MsgBox("Element " amp; elem.<TicketNumber>.Value amp; " deleted!")
            elem.<TicketNumber>.Remove()
        End If
    Next

    Console.WriteLine(doc.ToString)
    doc.Save(tst_xml_path amp; "tst.xml")
  

Итак, я попробовал ваш полный код со следующими изменениями:

     Public Sub Button5_Click() 'Removed the params to call the function easily.

    Dim deleteme As String = ("01451947504") 'Debug Var for string comapre
    Dim doc As New XmlDocument()
    doc.Load(path amp; FileXml)

    Dim Nodes = doc.SelectNodes("//TicketNumber")
    For Each elem As XmlElement In Nodes
        If elem.InnerText = deleteme Then
            elem.ParentNode.ParentNode.RemoveChild(elem.ParentNode)
            MsgBox("Element Deleted! ", MsgBoxStyle.Critical) 'amp; TicketNumber.ToString)  'Edited the MessageBox         
        End If
    Next
    doc.Save(path amp; "ouput.xml") 'Edited the ouput file for debug purpose
End Sub
  

Я просто вызываю это в своей основной функции следующим образом…

 Dim Tst = New Form1
Tst.Button5_Click()
  

И все прошло нормально. Я могу удалить каждую из 3 таблиц данных, которые вы написали в вашем примере XML-файла…

Комментарии:

1. когда я попробовал этот код, я получил ошибку, данные на корневом уровне недопустимы. Строка 1, позиция 1.

2. Это привело к двум небольшим проблемам с вашими XML-данными. Первое: вам нужно завершить раздел <sales_audit_xml> Второе: не вставляйте строку заголовка в строку. Это не сработает

3. Я ищу чтение в своем XML-файле, поскольку это будет большой XML-файл

4. когда я попытался это сделать, я получил данные об ошибке на корневом уровне, недопустимые. Строка 1, позиция 1. Я хотел бы также иметь возможность записывать код в текстовое поле

5. Можете ли вы сказать мне, что именно вы анализируете прямо сейчас? Я создал текстовый файл с xml, как вы написали в своем сообщении. Я вижу, что вы это исправили. Ошибка возникает при загрузке вашего полного документа или тестовый документ содержит только строки, которые вы написали в своем вопросительном сообщении?