Mam schemat, który weryfikuje mój plik XML, ale chcę dokonywać dalszych walidacji, takich jak zakresy numeryczne, struktura urodzinowa np. Dd / mm / yy not mm / dd / yy. Nazwa ucznia pozwala na znaki specjalne, np. _ W imieniu itp. W tej chwili, kiedy uruchomię mój kod, otrzymuję błąd:
[Błąd]: Dane na poziomie korzenia są nieprawidłowe. Linia 1, pozycja 1. W systemie.xml.xmltextreaderimpl.Throw (wyjątek e)

Próbka mojego XML:

 <?xml version="1.0" encoding="us-ascii" standalone="yes"?>
  <studentTable xmlns="namespace">

    <student>
      <ID>0</ID>
      <student_name>John</student_name>
      <birthday>25/09/1997</birthday>
    </student>

Próbowałem następującego kodu, ale otrzymałem błąd "Dane na poziomie korzenia jest nieprawidłowe. Linia 1, pozycja 1. w System.xml.xmltextreaderimpl.Throw (wyjątek e)"

        Dim xdoc As XmlDocument
        Dim nodelist As XmlNodeList
        Dim node As XmlNode
        Dim ID, birthday, student_name As String

        xdoc = New XmlDocument

        xdoc.LoadXml("student2.xml")

        nodelist = xdoc.SelectNodes("/studentTable/student")

        For Each node In nodelist

            ID = node.ChildNodes.Item(0).Attributes.GetNamedItem("ID").Value
            birthday = node.ChildNodes.Item(1).Attributes.GetNamedItem("birthday").Value
            student_name = node.ChildNodes.Item(2).Attributes.GetNamedItem("student_name").Value

        Dim rgx As New Regex("^[0-9]*$")
            If rgx.IsMatch(ID) = False Then
                lstErrs.Add("Invalid ID number")
            End If

        Dim reg As New Regex("^(((0[1-9]|[12]\d|3[01])\/(0[13578]|1[02])\/((19|[2-9]\d)\d{2}))|((0[1-9]|[12]\d|30)\/(0[13456789]|1[012])\/((19|[2-9]\d)\d{2}))|((0[1-9]|1\d|2[0-8])\/02\/((19|[2-9]\d)\d{2}))|(29\/02\/((1[6-9]|[2-9]\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))))$")
            If reg.IsMatch(birthday) = False Then
                lstErrs.Add("Invalid birthday")
            End If

        Dim regx As New Regex("^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$")
            If regx.IsMatch(student_name) = False Then
                lstErrs.Add("Invalid Name")
            End If

        Next

Błędy XML.

        If lstErrs.Count > 0 Then

                '-- Output list of errors
                MsgBox("Complete but with errors! Check error file.") '& vbCrLf & vbCrLf & Strings.Join(lstErrs.ToArray, vbCrLf))
                fileWriter.WriteLine("Filename:   " & 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]: " & exOther.Message & 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} " & e.Message)
        Case XmlSeverityType.Warning
            lstErrs.Add("Warning {0} " & e.Message)
        Case Else
            lstErrs.Add(e.Message)

    End Select
End Sub

Próbowałem zmienić LOADXML, aby po prostu załadować, ale mój kod działa bez błędu, ale mój Regex nie weryfikuje wartości XML. Jakakolwiek pomoc będzie wspaniała, dzięki.

0
user11096438 25 luty 2019, 17:05

2 odpowiedzi

Najlepsza odpowiedź

Jak wiesz, że jest tylko jeden <ID>, <birthday>, <birthday> itp. W każdym węźle <student> można użyć SelectSingleNode.

Chociaż wygląda jak .Value dostaniesz Cię, co wydaje się być wartością, jest bardziej trafnie niż: XMLNODE Wartość vs IntterText.

Zakładam, że umieściłeś w xmlns="namespace", widząc podobne rzeczy w innych XML. W tym przypadku, chyba że tak naprawdę go używasz, tylko skomplikuje sprawy.

Aby zatwierdzić datę, użyj DateTime.tryparseExact i daj mu ciąg formatu - nie ma potrzeby skomplikowanego regexa, który musiałby być inny, jeśli zmieniłeś się na lepszy format daty, takich jak YYYY-MM-DD.

Równie dobrze możesz zadeklarować regenety poza pętlą, aby utrzymać kod wewnątrz pętli trochę upłynniej.

Zawsze jest frustrujące, aby uzyskać wiadomość, która mówi coś takiego jak "Błąd daty", gdy nie mówi ci, gdzie lub jakie są błędne dane.

Tak więc, z tym plikiem XML umieszczony w moim katalogu "C: TEMP" (nie wiem, dlaczego użyłeś "US-ASCII", a nie "UTF-8"):

<?xml version="1.0" encoding="us-ascii" standalone="yes"?>
<studentTable>
    <student>
        <ID>0q</ID>
        <student_name>John*</student_name>
        <birthday>25/109/1997</birthday>
    </student>
</studentTable>

Oraz ta aplikacja konsola :

Imports System.Text.RegularExpressions
Imports System.Xml

Module Module1

    Sub Main()
        Dim lstErrs As New List(Of String)

        Dim idRegex = New Regex("^[0-9]*$")
        Dim nameRegex = New Regex("^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$")
        Dim dateFormat = "d/M/yyyy"

        Dim xdoc As New XmlDocument()
        xdoc.Load("C:\Temp\students.xml")

        Dim nodelist = xdoc.SelectNodes("//studentTable/student")

        For Each node As XmlNode In nodelist

            Dim id = node.SelectSingleNode("//ID").InnerText
            Dim dob = node.SelectSingleNode("//birthday").InnerText
            Dim name = node.SelectSingleNode("//student_name").InnerText

            If Not idRegex.IsMatch(id) Then
                lstErrs.Add("Invalid ID number " & id)
            End If

            If Not DateTime.TryParseExact(dob, dateFormat, Nothing, Nothing, New DateTime) Then
                lstErrs.Add("Invalid birthday " & dob)
            End If

            If Not nameRegex.IsMatch(name) Then
                lstErrs.Add("Invalid Name " & name)
            End If

            Console.WriteLine($"{id} {dob} {name}") '' for checking

        Next

        Console.WriteLine(String.Join(vbCrLf, lstErrs)) '' show the errors

        Console.ReadLine()

    End Sub

End Module

Mam to wyjście:

0q 25/109/1997 John*
Invalid ID number 0q
Invalid birthday 25/109/1997
Invalid Name John*
0
Andrew Morton 26 luty 2019, 19:03

Nie podaj żadnych okoliczności, spróbuj analizować XML z regexa, chyba że chcesz wywołać Rite 6 6 6 ph'ngui mglw'nafh cthulhu r'lyeh wgah'nagl fhtagn. .

Użyj biblioteki analizowania XML Patrz Ta strona w pewnym sensie, aby to zrobić za pomocą C # .NET. Należy to zamienić do VB.NET

Edytuj: Dalej do komentarzy. Spróbuj użyć Schemat XML w celu zatwierdzenia danych

-2
JGNI 25 luty 2019, 15:26