Uso de Python y lxml para validar XML contra una DTD externa

Estoy tratando de validar un archivo XML contra un DTD externo al que se hace referencia en la etiqueta doctype. Específicamente:

  ...the rest of the document... 

Estoy usando Python 3.3 y el módulo lxml. Después de leer http://lxml.de/validation.html#validation-at-parse-time , he lanzado esto juntos:

 enexFile = open(sys.argv[2], mode="rb") # sys.argv[2] is the path to an XML file in local storage. enexParser = etree.XMLParser(dtd_validation=True) enexTree = etree.parse(enexFile, enexParser) 

Por lo que entiendo de validation.html, la biblioteca lxml ahora debería encargarse de recuperar la DTD y realizar la validación. Pero en cambio, me sale esto:

 $ ./mapwrangler.py validate notes.enex Traceback (most recent call last): File "./mapwrangler.py", line 27, in  enexTree = etree.parse(enexFile, enexParser) File "lxml.etree.pyx", line 3239, in lxml.etree.parse (src/lxml/lxml.etree.c:69955) File "parser.pxi", line 1769, in lxml.etree._parseDocument (src/lxml/lxml.etree.c:102257) File "parser.pxi", line 1789, in lxml.etree._parseFilelikeDocument (src/lxml/lxml.etree.c:102516) File "parser.pxi", line 1684, in lxml.etree._parseDocFromFilelike (src/lxml/lxml.etree.c:101442) File "parser.pxi", line 1134, in lxml.etree._BaseParser._parseDocFromFilelike (src/lxml/lxml.etree.c:97069) File "parser.pxi", line 582, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:91275) File "parser.pxi", line 683, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:92461) File "parser.pxi", line 622, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:91757) lxml.etree.XMLSyntaxError: Validation failed: no DTD found !, line 3, column 43 

Esto me sorprende, porque si desactivo la validación, el documento se analiza perfectamente y puedo print(enexTree.docinfo.doctype) para obtener

 $ ./mapwrangler.py validate notes.enex  

Así que me parece que no debería haber ningún problema para encontrar la DTD.

Gracias por tu ayuda.

no_network=False agregar no_network=False al construir el objeto de analizador. Esta opción se establece en True de forma predeterminada.

De la documentación de las opciones del analizador en http://lxml.de/parsing.html#parsers :

no_network: impide el acceso a la red al buscar documentos externos (activado de forma predeterminada)

Por una razón que aún no sé, mi problema estaba relacionado con la ubicación del catálogo XML en mi sistema de archivos local.

En mi caso, utilizo un editor XML que tiene una estrecha integración con un sistema de gestión de contenido de componentes (CCMS, en este caso, SDL Trisoft 2011 R2). Cuando el editor se conecta al CCMS, las DTD, los archivos de catálogo y un montón de otros archivos se sincronizan. Estos archivos terminan en el sistema de archivos local en:

 C:\Users\[username]\AppData\Local\Trisoft\InfoShare Client\[id]\Config\DocTypes\catalog.xml 

No pude conseguir que funcione. Simplemente COPIANDO todo el catálogo a otra ubicación fija, y esto funciona:

 f = r"path/to/my/file.xml" # set XML catatog file path os.environ['XML_CATALOG_FILES'] = r'C:\DATA\Mydoctypes\catalog.xml' # configure parser parser = etree.XMLParser(dtd_validation=True, no_network=True) # validate try: valid = etree.parse(f, parser=parser) print("This file is valid against the DTD.") except etree.XMLSyntaxError, error: print("This file is INVALID against the DTD!") print(error) 

Obviamente esto no es lo ideal, pero funciona.

¿Podría ser algo que ver con los permisos de archivos, o tal vez ese problema antiguo de “ruta de archivo demasiado larga” en Windows? No he probado si un enlace simbólico funcionaría.

Estoy usando Windows 7, Python 2.7.11 y la versión de lxml es (3.6.0).