2017-06-02 3 views
3

Ich habe ein wirklich seltsames Problem, ein XML-Dokument gegen eine gültige XSD mit C# XDocument.Validate oder XMLReaderSettings mit erforderlichen Konfigurationen zu validieren. Das Problem ist: Wenn im XML-Dokument Fehler auftreten, kann der Validierungsprozess unter bestimmten Bedingungen nicht alle Fehler erfassen, und ich kann kein Muster für diese Anomalität finden.XDocument.Validate nicht alle Fehler gegen XSD

Hier ist meine XSD:

<?xml version="1.0" encoding="utf-8"?> 
 
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" 
 
\t \t \t targetNamespace="http://www.somesite.com/somefolder/messages" 
 
\t \t \t xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
 
    <xs:element name="Message"> 
 
    <xs:complexType> 
 
    <xs:sequence> 
 
     <xs:element name="Header"> 
 
     <xs:complexType> 
 
      <xs:sequence> 
 
      <xs:element name="MessageId" type="xs:string" /> 
 
      <xs:element name="MessageSource" type="xs:string" /> 
 
      </xs:sequence> 
 
     </xs:complexType> 
 
    </xs:element> 
 
    <xs:element name="Body"> 
 
     <xs:complexType> 
 
      <xs:sequence> 
 
      <xs:element name="Abc001"> 
 
       <xs:complexType> 
 
        <xs:sequence> 
 
        <xs:element name="Abc002" type="xs:string" /> 
 
        <xs:element name="Abc003" type="xs:string" minOccurs="0" /> 
 
        <!--<xs:element name="Abc004" type="xs:string" />--> 
 
        <xs:element name="Abc004"> 
 
         <xs:simpleType> 
 
         <xs:restriction base="xs:string"> 
 
          <xs:maxLength value="200"/> 
 
         </xs:restriction> 
 
         </xs:simpleType> 
 
        </xs:element> 
 
         <xs:element name="Abc005"> 
 
         <xs:complexType> 
 
          <xs:sequence> 
 
           <xs:element name="Abc006" type="xs:unsignedShort" /> 
 
           <xs:element name="Abc007"> 
 
           <xs:complexType> 
 
            <xs:sequence> 
 
            <xs:element name="Abc008" type="xs:string"/> 
 
            <xs:element name="Abc009" type="xs:string" minOccurs="0"/> 
 
            <xs:element name="Abc010" type="xs:string"/> 
 
            </xs:sequence> 
 
           </xs:complexType> 
 
           </xs:element> 
 
           <xs:element name="Abc011" type="xs:date" /> 
 
           <xs:element name="Abc012"> 
 
           <xs:complexType> 
 
            <xs:sequence> 
 
            <xs:element name="Abc013" type="xs:string" /> 
 
            <xs:element name="Abc014" type="xs:string" /> 
 
            </xs:sequence> 
 
           </xs:complexType> 
 
           </xs:element> 
 
          </xs:sequence> 
 
         </xs:complexType> 
 
         </xs:element> 
 
        </xs:sequence> 
 
       </xs:complexType> 
 
      </xs:element> 
 
      </xs:sequence> 
 
     </xs:complexType> 
 
    </xs:element> 
 
    </xs:sequence> 
 
    </xs:complexType> 
 
</xs:element> 
 
</xs:schema>

Und hier ist das XML-Dokument gegen diese XSD validiert:

<?xml version="1.0" encoding="utf-8"?> 
 
<Message xmlns="http://www.somesite.com/somefolder/messages"> 
 
\t <Header> 
 
\t \t <MessageId>Lorem</MessageId> 
 
\t \t <MessageSource>Ipsum</MessageSource> 
 
\t </Header> 
 
\t <Body> 
 
\t \t <Abc001> 
 
\t \t \t <Abc002>dolor</Abc002> 
 
\t \t \t <Abc003>sit amet</Abc003> 
 
\t \t \t <Abc004>consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</Abc004> 
 
\t \t \t <Abc005> 
 
\t \t \t \t <Abc006>1234</Abc006> 
 
\t \t \t \t <Abc007> 
 
\t \t \t \t \t <Abc008>Ut enim</Abc008> 
 
\t \t \t \t \t <Abc009>ad</Abc009> 
 
\t \t \t \t \t <Abc010>minim</Abc010> 
 
\t \t \t \t </Abc007> 
 
\t \t \t \t <Abc011>1982-10-17</Abc011> 
 
\t \t \t \t <Abc012> 
 
\t \t \t \t \t <Abc013>veniam</Abc013> 
 
\t \t \t \t \t <Abc014>nostrud</Abc014> 
 
\t \t \t \t </Abc012> 
 
\t \t \t </Abc005> 
 
\t \t </Abc001> 
 
\t </Body> 
 
</Message>
Nun, wenn ich einige Validierungsfehler in das XML einfüge und es gegen das XSD validiere, findet es alle Fehler wie erwartet. Hier ist die fehleranfällige xml (I markiert, wo die Fehler eingeführt werden):

<?xml version="1.0" encoding="utf-8"?> 
 
<Message xmlns="http://www.somesite.com/somefolder/messages"> 
 
\t <Header> 
 
\t \t <MessageId>Lorem</MessageId> 
 
\t \t <MessageSource>Ipsum</MessageSource> 
 
\t </Header> 
 
\t <Body> 
 
\t \t <Abc001> 
 
\t \t \t <Abc002>dolor</Abc002> 
 
\t \t \t <Abc003>sit amet</Abc003> 
 
\t \t \t 
 
\t \t \t <!--The value for Abc004 is increased beyond the allowed 200 characters--> 
 
\t \t \t 
 
\t \t \t <Abc004>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</Abc004> 
 
\t \t \t <Abc005> 
 
\t \t \t \t <Abc006>1234</Abc006> 
 
\t \t \t \t <Abc007> 
 
\t \t \t \t \t <Abc008>Ut enim</Abc008> 
 
\t \t \t \t \t <ABC009>AD</ABC009> 
 
\t \t \t \t \t 
 
\t \t \t \t \t <!--<Abc010>minim</Abc010> Required element removed--> 
 
\t \t \t \t </Abc007> 
 
\t \t \t \t 
 
\t \t \t \t <!--Date formate below is wrong--> 
 
\t \t \t \t <Abc011>1982-10-37</Abc011> 
 
\t \t \t \t 
 
\t \t \t \t <Abc012> 
 
\t \t \t \t \t <Abc013>veniam</Abc013> 
 
\t \t \t \t \t <Abc014>nostrud</Abc014> 
 
\t \t \t \t </Abc012> 
 
\t \t \t </Abc005> 
 

 
\t \t \t <!--the element below is not allowed--> 
 
\t \t \t <Abc15>Not allowed</Abc15> 
 
\t \t </Abc001> 
 
\t </Body> 
 
</Message>

und hier ist meine resultierende xml, das zeigt alle Fehler:

<MessageResponse xmlns="http://www.somesite.com/somefolder/messages"> 
 
    <Result>false</Result> 
 
    <Status>Failed</Status> 
 
    <FaultCount>4</FaultCount> 
 
    <Faults> 
 
     <Fault> 
 
      <FaultCode>ERR01</FaultCode> 
 
      <FaultMessage>The 'http://www.somesite.com/somefolder/messages:Abc004' element is invalid - The value 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.' is invalid according to its datatype 'String' - The actual length is greater than the MaxLength value.</FaultMessage> 
 
     </Fault> 
 
     <Fault> 
 
      <FaultCode>ERR02</FaultCode> 
 
      <FaultMessage>The element 'Abc007' in namespace 'http://www.somesite.com/somefolder/messages' has invalid child element 'ABC009' in namespace 'http://www.somesite.com/somefolder/messages'. List of possible elements expected: 'Abc009, Abc010' in namespace 'http://www.somesite.com/somefolder/messages'.</FaultMessage> 
 
     </Fault> 
 
     <Fault> 
 
      <FaultCode>ERR03</FaultCode> 
 
      <FaultMessage>The 'http://www.somesite.com/somefolder/messages:Abc011' element is invalid - The value '1982-10-37' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:date' - The string '1982-10-37' is not a valid Date value.</FaultMessage> 
 
     </Fault> 
 
     <Fault> 
 
      <FaultCode>ERR04</FaultCode> 
 
      <FaultMessage>The element 'Abc001' in namespace 'http://www.somesite.com/somefolder/messages' has invalid child element 'Abc15' in namespace 'http://www.somesite.com/somefolder/messages'.</FaultMessage> 
 
     </Fault> 
 
    </Faults> 
 
</MessageResponse>

Hier ist der seltsame Teil. Wenn ich einen weiteren Fehler am Anfang des Elements "Abc001" einfüge und auch alle anderen vorhandenen Fehler behalte, ist das Ergebnis völlig durcheinander. Hier ist der XML mit dem neu eingeführten Fehler:

<?xml version="1.0" encoding="utf-8"?> 
 
<Message xmlns="http://www.somesite.com/somefolder/messages"> 
 
\t <Header> 
 
\t \t <MessageId>Lorem</MessageId> 
 
\t \t <MessageSource>Ipsum</MessageSource> 
 
\t </Header> 
 
\t <Body> 
 
\t \t <Abc001> 
 
\t \t \t <!--newly introduced error - removed the following element--> 
 
\t \t \t <!--<Abc002>dolor</Abc002>--> 
 
\t \t \t <Abc003>sit amet</Abc003> 
 
\t \t \t <!--The value for Abc004 is increased beyond the allowed 200 characters--> 
 
\t \t \t <Abc004>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</Abc004> 
 
\t \t \t <Abc005> 
 
\t \t \t \t <Abc006>1234</Abc006> 
 
\t \t \t \t <Abc007> 
 
\t \t \t \t \t <Abc008>Ut enim</Abc008> 
 
\t \t \t \t \t <ABC009>AD</ABC009> 
 
\t \t \t \t \t <!--<Abc010>minim</Abc010>--> 
 
\t \t \t \t </Abc007> 
 
\t \t \t \t <Abc011>1982-10-37</Abc011> 
 
\t \t \t \t <Abc012> 
 
\t \t \t \t \t <Abc013>veniam</Abc013> 
 
\t \t \t \t \t <Abc014>nostrud</Abc014> 
 
\t \t \t \t </Abc012> 
 
\t \t \t </Abc005> 
 
\t \t \t <!--the element below is not allowed--> 
 
\t \t \t <Abc15>Not allowed</Abc15> 
 
\t \t </Abc001> 
 
\t </Body> 
 
</Message>

und schließlich, hier ist das Überprüfungsergebnis:

<MessageResponse xmlns="http://www.somesite.com/somefolder/messages"> 
 
    <Result>false</Result> 
 
    <Status>Failed</Status> 
 
    <FaultCount>1</FaultCount> 
 
    <Faults> 
 
     <Fault> 
 
      <FaultCode>ERR01</FaultCode> 
 
      <FaultMessage>The element 'Abc001' in namespace 'http://www.somesite.com/somefolder/messages' has invalid child element 'Abc003' in namespace 'http://www.somesite.com/somefolder/messages'. List of possible elements expected: 'Abc002' in namespace 'http://www.somesite.com/somefolder/messages'.</FaultMessage> 
 
     </Fault> 
 
    </Faults> 
 
</MessageResponse>

Hier ist mein C# -Code Ich verwende zur Validierung:

public async Task<IMIDPreValidationAckMessage> ValidateXmlMessage(XDocument doc) 
    { 
     var result = new PreValidationAckMessage(); 
     result.Result = true; 
     result.Status = "Succeeded"; 

     var xsd = HttpContext.Current.Server.MapPath("~/message01.xsd"); 

     try 
     { 
      var uri = new System.Uri(xsd); 

      var localPath = uri.LocalPath; 

      var docNameSpace = doc.Root.Name.Namespace.NamespaceName; 

      XmlSchemaSet schemas = new XmlSchemaSet(); 
      schemas.Add(docNameSpace, localPath); 

      XmlReaderSettings xrs = new XmlReaderSettings(); 
      xrs.ValidationType = ValidationType.Schema; 
      xrs.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; 
      xrs.Schemas = schemas; 

      result.XSDNamespace = doc.Root.GetDefaultNamespace().NamespaceName; 
      var errCode = 1; 

      xrs.ValidationEventHandler += (s, e) => 
      { 
       var msg = e.Message; 
       result.Result = false; 
       result.Status = "Failed"; 
       result.FaultCount++; 
       result.Faults.Add(new Fault 
       { 
        FaultCode = "ERR" + errCode++.ToString().PadLeft(2, '0'), 
        FaultMessage = e.Message 
       }); 
      }; 

      using (XmlReader xr = XmlReader.Create(doc.CreateReader(), xrs)) 
      { 
       while (xr.Read()) { } 
      } 
     } 
     catch (System.Exception ex) 
     { 
      result.Result = false; 
      result.Status = "Unknown Error"; 
     } 
     return result; 
    } 

Kann mir bitte jemand sagen, was hier nicht stimmt?

+0

Wäre gut, alle Klassen in Ihrem letzten Snippet aufzunehmen, nur damit Sie es kopieren und einfügen und ausführen können. – Evk

+0

@Evk: Danke für eine schnelle Antwort. Der Code, den ich nicht gepostet habe, sind verschachtelte Klassen und auch hier sind sie wirklich irrelevant. Wenn Sie die Fehlermeldungen nur einer Liste von Strings innerhalb des validationeventhandlers hinzufügen, sollte dies für den Test ausreichen. Mein Code erfasst nur die Fehlermeldungen und erstellt daraus ein weiteres XML-Dokument. Das ist alles. –

Antwort

1

Es scheint, dass XmlReader die Validierung des Elements beim ersten aufgetretenen Fehler stoppt. Hier ist ein Link zur Beschreibung der alten (veraltet) XmlValidatingReaderValidationEventHandler:

If an element reports a validation error, the rest of the content model for that element is not validated, however, its children are validated. The reader only reports the first error for a given element.

Und es scheint, es ist das gleiche mit regelmäßigen XmlReader (obwohl seine Dokumentation erwähnt nicht explizit).

In ersten Beispielen sind Fehler entweder in innersten Elementen (wie ungültiger Textwert von Element) oder im letzten untergeordneten Element, so dass sie alle gemeldet werden und nichts übersprungen wird.Im letzten Beispiel führen Sie jedoch einen Fehler am Anfang des root Abc001 Elements ein, so dass der Rest des Abc001 Inhalts zusammen mit allen Fehlern übersprungen wird.

+0

Nochmals vielen Dank für eine schnelle Antwort. Was Sie sagen, macht einen Sinn, obwohl ich den Eindruck hatte, dass die Validierung den gesamten Elementbaum durchläuft und über alle Fehler berichtet. Ich werde noch etwas länger auf andere Rückmeldungen warten, sagen Sie uns etwas anderes. Wenn keine andere Erklärung vorliegt, werde ich Ihre als angenommene Antwort markieren. Vielen Dank. –

+0

Sie können dies überprüfen, indem Sie Fehler in verschiedenen Teilen des Baums eingeben. Die Validierung endet nicht beim ersten Fehler im Allgemeinen, sondern nur beim ersten Fehler im angegebenen Teilbaum (Element). In Ihrem letzten Beispiel, wenn Sie mehrere 'Abc001'-Elemente hatten, wird nur das erste übersprungen (weil es direkt am Anfang einen Fehler hat), aber es wird mit den nachfolgenden Elementen fortgesetzt. Wenn Sie einen Fehler direkt nach dem '' Element eingeben, wird der Inhalt von 'Abc005' bis zu diesem Punkt analysiert. – Evk

+0

Ich habe vergessen, auf diese Frage zurückzukommen und die Antwort zu markieren. Es tut uns leid! Da kein anderes besseres Feedback erhalten und ich mit deinem Vorschlag getestet habe und aussieht, als ob du recht hast. Also, ich markiere dies als akzeptierte Antwort. Entschuldigung für die Verzögerung. –

Verwandte Themen