2010-07-25 28 views
5

prime pour la haute Q suivante:Comment valider un fichier xml par rapport à un schéma XSD en utilisant la bibliothèque Amara en Python?

Bonjour, Voici ce que j'ai essayé sur Ubuntu 9.10 en utilisant Python 2.6, Amara2 (en passant, test.xsd créé à l'aide xml2xsd outil):

[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===== 

Alors, pourquoi est-ce que je vois cette erreur? Cette fonctionnalité n'est-elle pas prise en charge? Comment puis-je valider un fichier XML par rapport à un fichier XSD tout en ayant la flexibilité pour pointer vers un fichier XSD? Merci, et laissez-moi savoir si vous avez des questions.

+0

êtes-vous prêt à utiliser la bibliothèque Amara? –

+0

@movieyoda, non, je peux passer à une autre bonne bibliothèque xml Python. Cependant, j'aurais besoin de porter mon code 'amara' existant, et j'espère trouver une solution indolore pour cela. –

Répondre

5

Si vous êtes ouvert à l'utilisation d'une autre bibliothèque en plus d'amara, essayez lxml. Il prend en charge ce que vous essayez de faire assez facilement:

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

Merci, je pourrais basculer - amara comme c'est un tracas. Comment puis-je faire quelque chose de similaire à 'pour q dans doc.quotes.quote: # La boucle va ramasser les deux éléments q de http://wiki.xml3k.org/Amara2/Tutorial? J'ai d'abord été vendu sur la liaison automatique, car il est censé être la façon pythonienne. Mais, mon malaise avec amara est en croissance ... –

+0

C'est une question distincte de l'original. (Mais comme je le ferais avec xpath ... 'pour q dans doc.xpath ('quotes/quote'): ...') Avec lxml vous pouvez faire à peu près n'importe quel xml/xsl/xpath/xsd tâche dont vous auriez besoin. – snapshoe

1

Je vous recommande d'utiliser noNamespaceSchemaLocation attribut pour lier le fichier XML au schéma XSD. Ensuite, votre fichier XML test.xml sera

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

où le fichier 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> 

doit être placé dans le même répertoire que le test.xsd. C'est une technique générale pour référencer le schéma XML du fichier XML et cela devrait fonctionner en Python.

L'avantage est que vous n'avez pas besoin de connaître le fichier de schéma pour chaque fichier XML. Il sera automatiquement trouvé lors de l'analyse (etree.parse) du fichier XML.

+0

Mais il veut la flexibilité de pointer vers n'importe quel XSD, pas seulement celui donné dans le fichier xml (le cas échéant). – snapshoe

+0

@ ma3204: Si quelqu'un écrit un document XML, il écrit qu'il correspond à un schéma. Vous ne devriez pas essayer d'interpréter le document dans un autre schéma. XML est un métalangage. XSD définit un langage spécifique. Si vous avez un texte écrit dans une langue, vous ne devriez pas essayer d'interpréter comme un texte dans une autre langue. Ainsi, seule la personne ** qui écrit ** un document XML peut spécifier le XSD pour cela. – Oleg

+0

Je mis à jour, mais mon cas d'utilisation est différent. Le Xml est généré automatiquement tous les jours (pour les tests), mais le schéma est fixé précisément parce que l'auto-générateur peut bousiller. –