2010-08-10 31 views
10

Quiero probar (verdadero o falso) si un archivo XML arbitrario coincide con un esquema dado.Usando .NET para validar XML contra un esquema

Por lo que vale, el esquema es el esquema WordML de Word 2003, que Microsoft define utilizando una lista de aproximadamente 7 *.xsd archivos.

Uno de estos archivos también incluye el archivo de W3C xml.xsd, al incluir la siguiente declaración:

<xsd:import id="xml" namespace="http://www.w3.org/XML/1998/namespace" 
    schemaLocation="http://www.w3.org/2001/xml.xsd"></xsd:import> 

estoy usando código .NET como el siguiente para hacer la validación:

public static void validate(string filename) 
    { 
     XmlReaderSettings settings = new XmlReaderSettings(); 
     settings.Schemas.Add(
      "http://schemas.microsoft.com/office/word/2003/wordml", 
      //to get this file I downloaded "Office 2003: XML Reference Schemas", i.e. "Office2003XMLSchema.exe" 
      @"C:\Program Files\Microsoft Office 2003 Developer Resources\Microsoft Office 2003 XML Reference Schemas\WordprocessingML Schemas\wordnet.xsd" 
      ); 
     settings.ValidationType = ValidationType.Schema; 
     settings.ValidationEventHandler += new ValidationEventHandler(validationEventHandler); 
     XmlReader xmlReader = XmlReader.Create(filename, settings); 
     while (xmlReader.Read()) { } 
    } 

Mi El problema es que si ejecuto este código en una máquina que no está conectada a Internet, entonces aparece un error XmlSchemaValidationException que indica que no puede encontrar xml.xsd.

Para solucionar esto, descargué una copia de xml.xsd y la agregué explícitamente usando el método settings.Schemas.Add: la validación ahora funciona correctamente cuando la máquina no está conectada a Internet.

Sin embargo, cuando la máquina está conectada a Internet, ahora recibo un error que dice The global attribute 'http://www.w3.org/XML/1998/namespace:lang' has already been declared..

Aparentemente, o bien tengo que agregarlo explícitamente, o no, dependiendo de si la máquina puede descargarlo silenciosamente de Internet (o incluso quizás haya sido capaz de descargarlo previamente, y lo ha almacenado en la memoria caché algun lado).

Por lo tanto, es "maldito si lo hago y maldito si no lo hago". ¿Debo intentarlo de una manera, atrapar la excepción y luego intentarlo de otra forma? ¿O hay una solución más elegante?

Respuesta

4

No podemos ver su código, pero En muchas implementaciones, esto se maneja al redirigir la solicitud de .xsd a la copia local utilizando una resolución de catálogo. Hay una propiedad XmlReaderSettings.XmlResolver que se puede usar para esto. Vea XMLCatalog.net para una implementación con licencia Apache que puede usar.

Un efecto secundario de esto es que puede mantener todos los esquemas en caché localmente. Esto es especialmente importante ya que W3C bloqueará lecturas excesivas en su sitio y al azar su código (o peor, el código de su cliente) comenzará a fallar.

+0

Gracias por la sugerencia; Voy a experimentar para ver si puedo solucionarlo usando una subclase 'System.Xml.XmlResolver'. – ChrisW

+1

Lo tengo trabajando ahora. Estaba fallando antes, porque estaba asignando a la propiedad 'XmlReaderSettings.XmlResolver'; pero cuando/porque estoy usando 'settings.Schemas.Add', necesitaba asignar a la propiedad' settings.Schemas.XmlResolver'. – ChrisW

+1

@ChrisW: También recibo el error "El atributo global 'http://www.w3.org/XML/1998/namespace:lang' ya ha sido declarado.", Con un código similar al de su pregunta original. ¿Estableciste las configuraciones.Schemas.XmlResolver al XMLCatalogResolver o algo más? Lo intenté sin suerte. ¿Alguna posibilidad de pegar tu código de trabajo? – Jeremy

Cuestiones relacionadas