Validando com um esquema XML em Python


104

Eu tenho um arquivo XML e um esquema XML em outro arquivo e gostaria de validar se meu arquivo XML está de acordo com o esquema. Como faço isso em Python?

Eu prefiro algo usando a biblioteca padrão, mas posso instalar um pacote de terceiros, se necessário.

Respostas:


61

Estou assumindo que você quer dizer usar arquivos XSD. Surpreendentemente, não existem muitas bibliotecas XML python que suportam isso. lxml, entretanto. Verifique a validação com lxml . A página também lista como usar lxml para validar com outros tipos de esquema.


1
lxml é python puro ou não? (requer compilação / instalação ou você pode apenas incluí-lo com seus scripts Python)
sorin

9
@Sorin: lxml é um wrapper no topo da biblioteca C libxml2 e, portanto, não é Python puro.
Eli Courtwright

2
@eli Exatamente o que eu queria sublinhar, isso pode não ser apropriado para ninguém.
Sorin

1
Os erros de validação não são fáceis de usar. Como eu faria isso? mailman-mail5.webfaction.com/pipermail/lxml/2012-April/… não ajuda.
Nenhum

Esta resposta ainda está atualizada?
Humano

27

Quanto às soluções "puramente python": o índice do pacote lista:

  • pyxsd , a descrição diz que ele usa xml.etree.cElementTree, que não é "python puro" (mas incluído no stdlib), mas o código-fonte indica que ele volta para xml.etree.ElementTree, então isso seria considerado python puro. Ainda não usei, mas de acordo com a documentação, ele faz validação de esquema.
  • minixsv : 'um validador de esquema XML leve escrito em Python "puro"'. No entanto, a descrição diz "atualmente, um subconjunto do padrão de esquema XML é compatível", portanto, isso pode não ser suficiente.
  • XSV , que eu acho que é usado para o validador xsd online do W3C (ele ainda parece usar o antigo pacote pyxml, que eu acho que não é mais mantido)

5
Eu daria uma olhada no PyXB sobre isso. Parece que a maioria desses estados estão incompletos e parecem um tanto "mortos". pyxsd atualizado pela última vez em 2006, minixsv atualizado pela última vez em 2008, XSV em 2007, tanto quanto posso dizer. Nem sempre a melhor razão para considerar um pacote em detrimento de outro, mas acho que se justifica neste caso.
oob

2
1 para PyXB. Estou usando no Django para validar XML bruto inserido na seção Admin. Simples e fácil de usar.
tatlar

21

Um exemplo de validador simples em Python3 usando a popular biblioteca lxml

Instalação lxml

pip install lxml

Se você receber um erro como "Não foi possível encontrar a função xmlCheckVersion na biblioteca libxml2. O libxml2 está instalado?" , tente fazer isso primeiro:

# Debian/Ubuntu
apt-get install python-dev python3-dev libxml2-dev libxslt-dev

# Fedora 23+
dnf install python-devel python3-devel libxml2-devel libxslt-devel

O validador mais simples

Vamos criar o validator.py mais simples

from lxml import etree

def validate(xml_path: str, xsd_path: str) -> bool:

    xmlschema_doc = etree.parse(xsd_path)
    xmlschema = etree.XMLSchema(xmlschema_doc)

    xml_doc = etree.parse(xml_path)
    result = xmlschema.validate(xml_doc)

    return result

em seguida, escreva e execute main.py

from validator import validate

if validate("path/to/file.xml", "path/to/scheme.xsd"):
    print('Valid! :)')
else:
    print('Not valid! :(')

Um pouco de OOP

Para validar mais de um arquivo, não há necessidade de criar um XMLSchema objeto todas as vezes, portanto:

validator.py

from lxml import etree

class Validator:

    def __init__(self, xsd_path: str):
        xmlschema_doc = etree.parse(xsd_path)
        self.xmlschema = etree.XMLSchema(xmlschema_doc)

    def validate(self, xml_path: str) -> bool:
        xml_doc = etree.parse(xml_path)
        result = self.xmlschema.validate(xml_doc)

        return result

Agora podemos validar todos os arquivos no diretório da seguinte maneira:

main.py

import os
from validator import Validator

validator = Validator("path/to/scheme.xsd")

# The directory with XML files
XML_DIR = "path/to/directory"

for file_name in os.listdir(XML_DIR):
    print('{}: '.format(file_name), end='')

    file_path = '{}/{}'.format(XML_DIR, file_name)

    if validator.validate(file_path):
        print('Valid! :)')
    else:
        print('Not valid! :(')

Para mais opções, leia aqui: Validação com lxml


14

O pacote PyXB em http://pyxb.sourceforge.net/ gera ligações de validação para Python a partir de documentos de esquema XML. Ele lida com quase todas as construções de esquema e oferece suporte a vários namespaces.


12

Existem duas maneiras (na verdade, existem mais) de fazer isso.
1. usando lxml
pip install lxml

from lxml import etree, objectify
from lxml.etree import XMLSyntaxError

def xml_validator(some_xml_string, xsd_file='/path/to/my_schema_file.xsd'):
    try:
        schema = etree.XMLSchema(file=xsd_file)
        parser = objectify.makeparser(schema=schema)
        objectify.fromstring(some_xml_string, parser)
        print "YEAH!, my xml file has validated"
    except XMLSyntaxError:
        #handle exception here
        print "Oh NO!, my xml file does not validate"
        pass

xml_file = open('my_xml_file.xml', 'r')
xml_string = xml_file.read()
xml_file.close()

xml_validator(xml_string, '/path/to/my_schema_file.xsd')
  1. Use xmllint na linha de comando. O xmllint vem instalado em muitas distribuições de Linux.

>> xmllint --format --pretty 1 --load-trace --debug --schema /path/to/my_schema_file.xsd /path/to/my_xml_file.xml


Eu tenho 3 arquivos xsd, somente quando todos os 3 xsd estão presentes posso validar um xml ... isso pode ser feito com o seu método?
Naveen

9

Você pode validar facilmente um arquivo ou árvore XML em um Esquema XML (XSD) com o pacote xmlschema Python . É Python puro, disponível no PyPi e não tem muitas dependências.

Exemplo - validar um arquivo:

import xmlschema
xmlschema.validate('doc.xml', 'some.xsd')

O método gera uma exceção se o arquivo não for validado no XSD. Essa exceção contém alguns detalhes de violação.

Se quiser validar muitos arquivos, você só precisa carregar o XSD uma vez:

xsd = xmlschema.XMLSchema('some.xsd')
for filename in filenames:
    xsd.validate(filename)

Se você não precisa da exceção, pode validar desta forma:

if xsd.is_valid('doc.xml'):
    print('do something useful')

Como alternativa, xmlschema funciona diretamente em objetos de arquivo e em árvores XML de memória (criadas com xml.etree.ElementTree ou lxml). Exemplo:

import xml.etree.ElementTree as ET
t = ET.parse('doc.xml')
result = xsd.is_valid(t)
print('Document is valid? {}'.format(result))

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.