#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, как вы написали в своем сообщении. Я вижу, что вы это исправили. Ошибка возникает при загрузке вашего полного документа или тестовый документ содержит только строки, которые вы написали в своем вопросительном сообщении?