validator - Validar XML con XSD
xml validator xsd (3)
Me encuentro con dificultades reales para validar XML con XSD . Debo prefijar todo esto y declarar desde el principio, soy nuevo en XSD y validación, por lo que no estoy seguro de si se trata de un problema de código o XML. He estado en el infierno de XML API y de nuevo con las diferentes opciones y creo que he encontrado cuál sería la estrategia ideal para validar XML con XSD. Tenga en cuenta que mi XML y XSD provienen de una base de datos, por lo que no necesito leer nada del disco.
Reduje mi problema a una simple aplicación de Windows Forms . Tiene un cuadro de texto para XSD (txtXsd), un cuadro de texto para XML (txtXml), un cuadro de texto para el resultado (txtResult) y un botón para iniciar la validación (btnValidate).
Estoy usando un archivo XSD de muestra de Microsoft,
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:bookstore-schema" elementFormDefault="qualified" targetNamespace="urn:bookstore-schema">
<xsd:element name="title" type="xsd:string" />
<xsd:element name="comment" type="xsd:string" />
<xsd:element name="author" type="authorName"/>
<xsd:complexType name="authorName">
<xsd:sequence>
<xsd:element name="first-name" type="xsd:string" />
<xsd:element name="last-name" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
Estoy usando el siguiente código en mi aplicación.
private void btnValidate_Click (object sender, EventArgs e)
{
try
{
XmlTextReader reader = new XmlTextReader(txtXsd.Text, XmlNodeType.Document, new XmlParserContext(null, null, String.Empty, XmlSpace.None));
XmlSchema schema = XmlSchema.Read(reader, null);
XmlSchemaSet schemas = new XmlSchemaSet();
schemas.Add(schema);
XDocument doc = XDocument.Parse(txtXml.Text);
doc.Validate(schemas, ValidateSchema);
}
catch (Exception exception)
{
txtResult.Text += exception.Message + Environment.NewLine;
}
}
private void ValidateSchema (Object sender, ValidationEventArgs e)
{
txtResult.Text += e.Message + Environment.NewLine;
}
Como prueba, puse XML válido, pero lo que creo que no debería ser conforme al XSD anterior.
<xml>
<bogusNode>blah</bogusNode>
</xml>
El resultado es nada, ningún error de validación de ningún tipo. ¿Cómo lo arreglo?
Bueno, para empezar, su XSD define un espacio de nombres XML xmlns="urn:bookstore-schema"
que no está presente en su archivo de prueba XML; por lo tanto, no se validará nada en su archivo de prueba XML.
Si elimina esos elementos de su esquema:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="title" type="xsd:string" />
entonces validará correctamente su archivo de prueba XML y se quejará sobre los elementos incorrectos.
También usar un elemento llamado <xml>
podría no ser una buena idea, ya que la directiva <?xml ......?>
Es una directiva predefinida y no debe aparecer como nombre de etiqueta en ningún otro lugar de su documento.
Bagazo
También puede probar XmlValidatingReader para la validación de XML
No quiero que el usuario envíe XML que no está definido en el XSD.
¿Por qué te importa? Su esquema valida los nodos XML que están en su espacio de nombres. Su lógica de procesamiento procesa los nodos XML que están en su espacio de nombres. Los nodos que no están en su espacio de nombres no son relevantes ni para su esquema ni para su lógica.
Si es realmente esencial restringir todos los nodos en el documento XML a un espacio de nombre específico, puede lograr eso extendiendo la lógica de validación XmlReader
básica que se encuentra aquí .
public static void Main()
{
const string myNamespaceURN = "urn:my-namespace";
XmlSchemaSet sc = new XmlSchemaSet();
sc.Add(myNamespaceURN, "mySchema.xsd");
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
settings.Schemas = sc;
settings.ValidationEventHandler += ValidationCallBack;
XmlReader reader = XmlReader.Create("myDocument.xml", settings);
while (reader.Read())
{
if ((reader.NodeType == XmlNodeType.Element ||
reader.NodeType == XmlNodeType.Attribute)
&&
reader.NamespaceURI != myNamespaceURN)
{
LogError(reader.NamespaceURI + " is not a valid namespace.");
}
}
}
private static void ValidationCallBack(object sender, ValidationEventArgs e)
{
LogError(e.Message);
}
private static void LogError(string msg)
{
Console.WriteLine(msg);
}