2015-05-29 29 views
6

Mam klasę, która sprawdza poprawność dostarczonego dokumentu XML na podstawie dostarczonego XSD. W klasie I wywołać metodę XDocument.Validate sprawdzania poprawności, i otrzymuję następujący błąd:XDocument.Validate - Oczekiwany typ Typ elementu błędu

The ' http://www.example.com/enrollrequest1:requested-payment-date ' element is invalid - The value '2015-05-28T00:00:00' is invalid according to its datatype ' http://www.w3.org/2001/XMLSchema:date ' - The string '2015-05-28T00:00:00' is not a valid XsdDateTime value.

Wartość elementu została ustalona z .NET DateTime zmiennej, która ostatecznie odróżnia ją z czasem część zawartych, ponieważ istnieje brak odpowiednika xs: typ daty w .NET.

Wartości dla elementów są ustawiane z modułu ogólnego, więc nie mogę wybierać elementów i dostosowywać ich wartości. Programista wysyła wartość w typie .NET DateTime, który mój program z kolei wywołuje metodę XElemet.SetValue(value), aby ją ustawić.

Ponadto plik XSD jest poza kontrolą. Zatem modyfikowanie XSD nie jest opcją.

Czy istnieje sposób sprawdzenia, jaki jest oczekiwany typ XElement, który spowodował błąd? Gdy już się o tym dowiem, mogę po prostu wpisać typ lub odpowiednio dostosować mój kod. Na przykład w tym przypadku, jeśli wiem, że oczekiwany typ to xs:date (i nie xs:datetime), mogę po prostu wpisać wartość przychodzącą.

Oto moja klasa walidator, jeśli to pomoże:

Option Strict On 
Imports System.XML.Schema 

Public Class XmlSchemaValidator 
    Public ReadOnly Errors As New List(Of String) 

    Private XDoc As XDocument 
    Private Schemas As XmlSchemaSet 

    Public Sub New(ByVal doc As XDocument, ByVal schemaUri As String, ByVal targetNamespace As String) 
     Me.XDoc = doc 
     Me.Schemas = New XmlSchemaSet 
     Me.Schemas.Add(targetNamespace, schemaUri) 
    End Sub 

    Public Sub Validate() 
     Errors.Clear() 
     XDoc.Validate(Schemas, AddressOf XsdErrors) 
    End Sub 

    Private Sub XsdErrors(ByVal sender As Object, ByVal e As ValidationEventArgs) 
     Errors.Add (e.Message) 
    End Sub 
End Class 

Oto funkcja, która jest ustawia wartości węzeł XML.

Function SetValue(ByVal xmlDoc As XDocument, ByVal keyValues As Dictionary(Of String, Object)) As Boolean 
    '' set values 
    For Each kvp In keyValues 
     Dim xe As XElement = xmlDoc.Root.XPathSelectElement(kvp.Key) 

     ''-- this is buggy implementation for handling xs:date vs xs:datetime that needs to be corrected... 
     'If TypeOf kvp.Value Is DateTime AndAlso DirectCast(kvp.Value, DateTime).TimeOfDay = TimeSpan.Zero Then 
     ' xe.SetValue(DirectCast(kvp.Value, DateTime).ToString("yyyy-MM-dd")) 
     'Else 
     xe.SetValue(kvp.Value) 
     'End If 
    Next 

    '' validate final document 
    Dim schemaValidator As New XmlSchemaValidator(xmlDoc, schemaFile, "") 
    schemaValidator.Validate() 
    If schemaValidator.Errors.Count > 0 Then 
     'Error Logging code goes here... 
     Return False 
    End If 
    Return True 
End Function 
+0

Co byś pisał na ten temat _to_? Jak już powiedziałeś, nie ma klasy "System.Date". –

+0

Chcę wiedzieć, czego XSD oczekuje dla tego elementu - 'xs: date' lub' xs: time' lub 'xs: datetime', niezależnie od wartości ustawionej dla elementu. Resztę, którą mogę odpowiednio obsługiwać. –

+0

Więc na przykład, jeśli wiem, że błąd był, ponieważ podałem datetime zamiast tylko daty, mogę po prostu zrobić 'XElement.SetValue (value.ToString (" rrrr-MM-dd "))'. –

Odpowiedz

0

Napisałeś we wcześniejszym komentarzu:

„Chcę wiedzieć, co XSD spodziewa dla tego elementu”

Następnie, należy pamiętać, że można wykorzystać pierwszy parametr „nadawca "swoich koparki walidacji, na przykład, adapting this MSDN sample jak np

 string xsdMarkup = 
@"<xsd:schema xmlns:xsd='http://www.w3.org/2001/XMLSchema'> 
    <xsd:element name='Root'> 
    <xsd:complexType> 
    <xsd:sequence> 
     <xsd:element name='Child1' minOccurs='1' maxOccurs='1'/> 
     <xsd:element name='Child2' minOccurs='1' maxOccurs='1'/> 
    </xsd:sequence> 
    </xsd:complexType> 
    </xsd:element> 
    </xsd:schema>"; 
     XmlSchemaSet schemas = new XmlSchemaSet(); 
     schemas.Add("", XmlReader.Create(new StringReader(xsdMarkup))); 

     // (just for debug spying) 
     var schemata = new XmlSchema[1]; 
     schemas.CopyTo(schemata, 0); 

     XDocument errorDoc = new XDocument(
      new XElement("Root", 
       new XElement("Child1", "content1"), 
       new XElement("Child2", "content2"), 
       new XElement("Child2", "content3") // (must fail validation on maxOccurs) 
      ) 
     ); 

     Console.WriteLine(); 
     Console.WriteLine("Validating errorDoc"); 
     errorDoc.Validate(schemas, (sender, args) => 
     { 
      Console.WriteLine("{0}", args.Message); // (what you're already doing) 
      Console.WriteLine(); 
      // but there's also: 
      var xElement = sender as XElement; 
      if (xElement != null) 
      { 
       Console.WriteLine("Element {0} invalid : {1}", xElement, e.Exception.Message); 
      } 
     }); 

     Console.ReadKey(); 

to mogą przynieść wyjście z wystarczającą ilością informacji na temat rozpoznawalnych sprawców w dokumencie, miejmy nadzieję:

Validating errorDoc 
The element 'Root' has invalid child element 'Child2'. 

Element <Child2>content3</Child2> invalid : The element 'Root' has invalid child element 'Child2'. 

W każdym razie, gdy wiesz sprawcą nieważnego dokumentu, wtedy masz większe szanse, aby skorelować bardziej niezawodnie z odpowiednimi definicjami w schemacie (ów) stosowanego do tej walidacji (niż poleganie tylko na łańcuchu błędu sprawdzania schematu).

(przepraszam za odpowiedź w C# składni, ale raczej nie chciałbym napisać w niewłaściwej VB.NET, Dostaję zbyt zardzewiałe z, teraz)

„Nadzieja to pomaga.

Powiązane problemy