2008-09-22 8 views
5

J'ai certaines méthodes WCF qui sont utilisées pour transmettre des informations d'une application serveur à une interface de site Web pour une utilisation dans la liaison. J'envoie le résultat en tant que XElement qui est la racine d'un arbre XML contenant les données que je veux lier.Comment mieux tester la validité de XML à partir d'une méthode?

Je voudrais créer des tests qui examinent les données et vérifient qu'elles sont conformes aux attentes. Ma pensée actuelle est la suivante: Chaque méthode qui renvoie une arborescence XElement a un fichier schéma (.XSD) correspondant. Ce fichier est inclus dans l'assembly qui contient mes classes WCF en tant que ressource incorporée.

Les tests appellent la méthode sur ces méthodes et comparent le résultat avec ces schémas incorporés.

Est-ce une bonne idée? Sinon, quels autres moyens puis-je utiliser pour fournir une "garantie" du type de XML qu'une méthode retournera?

Si oui, comment validez-vous un XElement par rapport à un schéma? Et comment puis-je obtenir ce schéma de l'assemblage dans lequel il est intégré?

Répondre

11

Il est recommandé de valider un fichier xml avec un schéma xsd. Comment valider un XElement avec le schéma chargé: Comme vous le voyez dans cet exemple, vous devez d'abord valider le XDocument pour remplir l'infoset de validation post-schéma (il pourrait y avoir une solution pour cela sans en utilisant la méthode Valider sur la XDocument mais je suis encore en trouver un):

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; 
}); 

Comment lire le schéma intégré d'un ensemble et l'ajouter à la XmlSchemaSet:

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() renvoie NULL. – Will

+0

Je n'ai pas la méthode Validate sur le XDocument, c'est une méthode d'extension de quel namespace? –

+1

pour tous ceux qui recherchent également l'espace de nommage: using System.Xml.Schema; –

4

Si vous re faire un peu de travail léger et les XSD sont exagérés, pensez peut-être aussi en tapant fortement vos données XML. Par exemple, j'ai un certain nombre de classes dans un projet qui dérivent de XElement. L'un est ExceptionXElement, l'autre est HttpHeaderXElement, etc. Dans ceux-ci, j'hérite de XElement et j'ajoute des méthodes Parse et TryParse qui prennent des chaînes contenant des données XML pour créer une instance à partir de. Si TryParse() renvoie la valeur false, la chaîne n'est pas conforme aux données XML attendues (l'élément racine a le mauvais nom, les éléments enfants manquants, etc.).

Par exemple:

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... 
    } 
Questions connexes