2008-09-22 13 views
5

Ich habe einige WCF-Methoden, die verwendet werden, um Informationen von einer Serveranwendung an ein Website-Frontend für die Verwendung in Bindung zu übertragen. Ich sende das Ergebnis als ein XElement, das ein Stamm einer XML-Struktur ist, die die Daten enthält, an die ich binden möchte.Wie kann man die Gültigkeit von XML aus einer Methode am besten testen?

Ich möchte einige Tests erstellen, die die Daten untersuchen und sicherstellen, dass sie wie erwartet angezeigt werden.

Mein aktuelles Denken ist dies: Jede Methode, die eine XElement-Struktur zurückgibt, hat eine entsprechende Schema (XSD) -Datei. Diese Datei ist in der Assembly enthalten, die meine WCF-Klassen als eingebettete Ressource enthält.

Tests rufen die Methode für diese Methoden auf und vergleichen das Ergebnis mit diesen eingebetteten Schemas.

Ist das eine gute Idee? Wenn nicht, welche anderen Möglichkeiten kann ich verwenden, um eine "Garantie" dafür zu geben, welche Art von XML eine Methode zurückgibt?

Wenn ja, wie validiert man ein XElement gegen ein Schema? Und wie kann ich dieses Schema von der Assembly erhalten, in der es eingebettet ist?

Antwort

11

Id sagen Validierung xml mit einem xsd-Schema ist eine gute Idee. Wie Sie in diesem Beispiel sehen, müssen Sie zuerst das XDocument validieren, um das "Post-Schema-Validierungs-Infoset" zu füllen. (Es könnte eine Lösung geben, dies ohne zu tun.)
Wie validiert man ein XElement mit dem geladenen Schema: mit der Validate-Methode auf dem XDocument aber ich bin noch zu finden):

String xsd = 
@"<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:complexType> 
     <xsd:sequence> 
     <xsd:element name='grandchild1' minOccurs='1' maxOccurs='1'/> 
     <xsd:element name='grandchild2' minOccurs='1' maxOccurs='2'/> 
     </xsd:sequence> 
     </xsd:complexType> 
     </xsd:element> 
    </xsd:sequence> 
    </xsd:complexType> 
    </xsd:element> 
    </xsd:schema>"; 
String xml = @"<?xml version='1.0'?> 
<root> 
    <child1> 
     <grandchild1>alpha</grandchild1> 
     <grandchild2>beta</grandchild2> 
    </child1> 
</root>"; 
XmlSchemaSet schemas = new XmlSchemaSet(); 
schemas.Add("", XmlReader.Create(new StringReader(xsd))); 
XDocument doc = XDocument.Load(XmlReader.Create(new StringReader(xml))); 
Boolean errors = false; 
doc.Validate(schemas, (sender, e) => 
{ 
    Console.WriteLine(e.Message); 
    errors = true; 
}, true); 
errors = false; 
XElement child = doc.Element("root").Element("child1"); 
child.Validate(child.GetSchemaInfo().SchemaElement, schemas, (sender, e) => 
{ 
    Console.WriteLine(e.Message); 
    errors = true; 
}); 

Wie das eingebettete Schema aus einer Baugruppe zu lesen und zu XmlSchemaSet hinzufügen:

Assembly assembly = Assembly.GetExecutingAssembly(); 
// you can use reflector to get the full namespace of your embedded resource here 
Stream stream = assembly.GetManifestResourceStream("AssemblyRootNamespace.Resources.XMLSchema.xsd"); 
XmlSchemaSet schemas = new XmlSchemaSet(); 
schemas.Add(null, XmlReader.Create(stream)); 
+0

element.GetSchemaInfo() gibt den Wert null. – Will

+0

Ich habe nicht die Validate-Methode für das XDocument, dies ist eine Erweiterung Methode aus welchem ​​Namespace? –

+1

für alle, die auch nach dem Namensraum suchen: using System.Xml.Schema; –

4

Wenn Sie‘ re einige leichte Arbeit und XSDs sind Overkill, denken Sie möglicherweise auch stark Ihre XML-Daten eingeben. Zum Beispiel habe ich eine Anzahl von Klassen in einem Projekt, die von XElement abgeleitet sind. Eine davon ist ExceptionXElement, eine andere ist HttpHeaderXElement usw. In ihnen erben wir von XElement und fügen Parse- und TryParse-Methoden hinzu, die Strings mit XML-Daten enthalten, aus denen eine Instanz erstellt wird. Wenn TryParse() den Wert false zurückgibt, stimmt die Zeichenfolge nicht mit den erwarteten XML-Daten überein (das Stammelement hat den falschen Namen, fehlende untergeordnete Elemente usw.).

Zum Beispiel:

public class MyXElement : XElement 
{ 

    public MyXElement(XElement element) 
     : base(element) 
    { } 

    public static bool TryParse(string xml, out MyXElement myElement) 
    { 
     XElement xmlAsXElement; 

     try 
     { 
      xmlAsXElement = XElement.Parse(xml); 
     } 
     catch (XmlException) 
     { 
      myElement = null; 
      return false; 
     } 

     // Use LINQ to check if xmlAsElement has correct nodes... 
    }