2010-07-25 70 views
5

alta recompensa por la siguiente Q:¿Cómo validar un archivo xml contra un esquema XSD utilizando la biblioteca de Amara en Python?

Hola, Aquí es lo que he intentado en Ubuntu 9.10 usando Python 2.6, Amara2 (por cierto, se ha creado usando Test.xsd xml2xsd herramienta):

[email protected]:~$ cat test.xml; echo =====o=====; cat test.xsd; echo ==== 
o=====; cat test.py; echo =====o=====; ./test.py; echo =====o===== 
<?xml version="1.0" encoding="utf-8"?>==; ./test.py` > 
test.txttest.xsd; echo === 
<test>abcde</test> 
=====o===== 
<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
elementFormDefault="qualified"> 
    <xs:element name="test" type="xs:NCName"/> 
</xs:schema> 
=====o===== 
#!/usr/bin/python2.6 
# I wish to validate an xml file against an external XSD schema. 
from amara import bindery, parse 
source = 'test.xml' 
schema = 'test.xsd' 
#help(bindery.parse) 
#doc = bindery.parse(source, uri=schema, validate=True) # These 2 seem 
to fail in the same way. 
doc = parse(source, uri=schema, validate=True) # So, what is the 
difference anyway? 
# 
=====o===== 
Traceback (most recent call last): 
    File "./test.py", line 14, in <module> 
    doc = parse(source, uri=schema, validate=True) 
    File "/usr/local/lib/python2.6/dist-packages/Amara-2.0a4-py2.6-linux- 
x86_64.egg/amara/tree.py", line 50, in parse 
    return _parse(inputsource(obj, uri), flags, 
entity_factory=entity_factory) 
amara.ReaderError: In file:///home/g/test.xml, line 2, column 0: 
Missing document type declaration 
[email protected]:~$ 
=====o===== 

Entonces, ¿por qué veo este error? ¿Esta funcionalidad no es compatible? ¿Cómo puedo validar un archivo XML contra un XSD teniendo la flexibilidad de para apuntar a cualquier archivo XSD? Gracias, y avíseme si tiene alguna pregunta.

+0

¿Está usted empeñado en usar la Biblioteca Amara? –

+0

@movieyoda, no, puedo saltar a otra buena biblioteca de Python xml. Sin embargo, necesitaría portar mi código 'amara' existente entonces, y espero encontrar una solución indolora para eso. –

Respuesta

5

Si está abierto a utilizar otra biblioteca además de amara, intente lxml. Es compatible con lo que estamos tratando de hacer con bastante facilidad:

from lxml import etree 

source_file = 'test.xml' 
schema_file = 'test.xsd' 

with open(schema_file) as f_schema: 

    schema_doc = etree.parse(f_schema) 
    schema = etree.XMLSchema(schema_doc) 
    parser = etree.XMLParser(schema = schema) 

    with open(source_file) as f_source: 
     try: 
      doc = etree.parse(f_source, parser) 
     except etree.XMLSyntaxError as e: 
      # this exception is thrown on schema validation error 
      print e 
+0

Gracias, podría cambiar - amara como es una molestia. ¿Cómo puedo hacer algo similar a 'para q en doc.quotes.quote: # El ciclo recogerá los dos elementos q' desde http://wiki.xml3k.org/Amara2/Tutorial? Inicialmente, me vendieron el autoaglutinante, porque supuestamente es la forma pitónica. Pero, mi incomodidad con Amara está creciendo ... –

+0

Esa es una pregunta separada del original. (Pero la forma en que lo haría es con xpath ... 'para q en doc.xpath ('quotes/quote'): ...') Con lxml puedes hacer casi cualquier xml/xsl/xpath/xsd tarea que necesitarías – snapshoe

1

Voy a recomendar su uso noNamespaceSchemaLocation atributo para vincular el archivo XML en el esquema XSD. A continuación, el archivo XML test.xml será

<?xml version="1.0" encoding="utf-8"?> 
<test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xsi:noNamespaceSchemaLocation="test.xsd">abcde</test> 

donde el archivo Test.xsd

<?xml version="1.0" encoding="utf-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
      elementFormDefault="qualified"> 
    <xs:element name="test" type="xs:NCName"/> 
</xs:schema> 

se debe colocar en el mismo directorio que el Test.xsd. Es una técnica general hacer referencia al esquema XML desde el archivo XML y debería funcionar en Python.

La ventaja es que usted no necesita saber el archivo de esquema para cada archivo XML. Se encontrará automáticamente durante el análisis (etree.parse) del archivo XML.

+0

Pero él quiere la flexibilidad para apuntar a cualquier XSD, no solo el que figura en el archivo xml (si lo hay). – snapshoe

+0

@ ma3204: Si alguien escribe un documento XML, escribe que corresponde a un esquema. No intente interpretar el documento en otro esquema. XML es un metalenguaje. XSD define un lenguaje específico. Si tienes un texto escrito en un idioma que no debes tratar de interpretar es como un texto en otro idioma. Entonces, solo la persona ** que escribe ** un documento XML puede especificar el XSD para ello. – Oleg

+0

Subí, pero mi caso de uso es diferente. El Xml se genera automáticamente todos los días (para probar), pero el esquema se soluciona de forma precisa porque el autogenerador puede estropearse. –

Cuestiones relacionadas