2008-09-22 12 views
5

Tengo algunos métodos WCF que se utilizan para transmitir información de una aplicación de servidor a una interfaz de sitio web para su uso en enlace. Estoy enviando el resultado como un XElement que es una raíz de un árbol XML que contiene los datos que quiero vincular.¿Cuál es la mejor manera de probar la validez de XML a partir de un método?

Me gustaría crear algunas pruebas que examinen los datos y se aseguren de que funcionen como se esperaba.

Mi pensamiento actual es este: cada método que devuelve un árbol XElement tiene un archivo de esquema correspondiente (.XSD). Este archivo está incluido dentro del ensamblaje que contiene mis clases WCF como un recurso incrustado.

Las pruebas llaman al método en estos métodos y compara el resultado con estos esquemas incrustados.

¿Es esta una buena idea? Si no, ¿de qué otras maneras puedo usar para proporcionar una "garantía" de qué tipo de XML devolverá un método?

Si lo es, ¿cómo se valida un XElement contra un esquema? ¿Y cómo puedo obtener ese esquema del ensamblaje en el que está incrustado?

Respuesta

11

Id decir validar xml con un esquema xsd es una buena idea.

Cómo validar un XElement con el esquema cargado: Como ve en este ejemplo, primero debe validar el XDocument para obtener el "infoset de validación posterior al esquema" (Puede haber una solución para hacer esto sin utilizando el método Validar en el XDocument pero Im todavía encontrar uno):

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

Cómo leer el esquema incrustado desde un montaje y agregarlo a 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() devuelve un valor nulo. – Will

+0

No tengo el método Validate en el XDocument, este es un método de extensión del cual el espacio de nombres? –

+1

para cualquiera que también esté buscando el espacio de nombre: usando System.Xml.Schema; –

4

Si' re haciendo un trabajo liviano y los XSD son excesivos, considere también posiblemente tipear fuertemente sus datos XML. Por ejemplo, tengo varias clases en un proyecto que se derivan de XElement. Uno es ExceptionXElement, otro es HttpHeaderXElement, etc. En ellos, heredo de XElement y agrego los métodos Parse y TryParse que toman cadenas que contienen datos XML para crear una instancia. Si TryParse() devuelve falso, la cadena no se ajusta a los datos XML que espero (el elemento raíz tiene el nombre incorrecto, elementos secundarios faltantes, etc.).

Por ejemplo:

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... 
    } 
Cuestiones relacionadas