Memvalidasi dengan skema XML dengan Python

104

Saya memiliki file XML dan skema XML di file lain dan saya ingin memvalidasi bahwa file XML saya mematuhi skema. Bagaimana saya melakukan ini dengan Python?

Saya lebih suka sesuatu yang menggunakan pustaka standar, tetapi saya dapat menginstal paket pihak ketiga jika perlu.

Eli Courtwright
sumber

Jawaban:

61

Saya berasumsi maksud Anda menggunakan file XSD. Anehnya, tidak banyak pustaka XML python yang mendukung ini. Namun lxml tidak. Periksa Validasi dengan lxml . Halaman ini juga mencantumkan cara menggunakan lxml untuk memvalidasi dengan jenis skema lainnya.

Keegan Carruthers-Smith
sumber
1
lxml adalah python murni atau tidak? (memang membutuhkan kompilasi / instalasi atau Anda bisa memasukkannya dengan skrip python Anda)
sorin
9
@Sorin: lxml adalah pembungkus di atas pustaka C libxml2, dan karenanya bukan Python murni.
Eli Courtwright
2
@eli Persis seperti yang ingin saya garis bawahi, ini mungkin tidak sesuai untuk siapa pun.
sorin
1
Kesalahan validasi tidak ramah pengguna. Bagaimana saya akan melakukannya? mailman-mail5.webfaction.com/pipermail/lxml/2012-April/… tidak membantu.
Tidak ada-da
Apakah jawaban ini masih mutakhir?
Manusia
27

Adapun solusi "python murni": daftar indeks paket:

  • pyxsd , deskripsinya menyatakan bahwa ia menggunakan xml.etree.cElementTree, yang bukan "python murni" (tetapi disertakan dalam stdlib), tetapi kode sumber menunjukkan bahwa ia kembali ke xml.etree.ElementTree, jadi ini akan dihitung sebagai python murni. Belum pernah menggunakannya, tetapi menurut dokumen, ia melakukan validasi skema.
  • minixsv : 'validator skema XML ringan yang ditulis dalam Python "murni". Namun, deskripsi mengatakan "saat ini subset dari standar skema XML didukung", jadi ini mungkin tidak cukup.
  • XSV , yang menurut saya digunakan untuk validator xsd online W3C (sepertinya masih menggunakan paket pyxml lama, yang menurut saya tidak lagi dipertahankan)
Steven
sumber
5
Saya akan melihat PyXB atas ini. Sepertinya sebagian besar status ini tidak lengkap, dan tampaknya "mati". pyxsd terakhir diperbarui pada tahun 2006, minixsv terakhir diperbarui pada tahun 2008, XSV pada tahun 2007 sejauh yang saya tahu. Tidak selalu menjadi alasan terbaik untuk mempertimbangkan satu paket di atas yang lain, tetapi saya pikir itu dibenarkan dalam kasus ini.
oob
2
1 untuk PyXB. Saya menggunakannya di Django untuk memvalidasi XML mentah yang disisipkan di bagian Admin. Sederhana dan mudah digunakan.
tatlar
21

Contoh validator sederhana di Python3 menggunakan pustaka populer lxml

Instalasi lxml

pip install lxml

Jika Anda mendapatkan pesan kesalahan seperti "Tidak dapat menemukan fungsi xmlCheckVersion di perpustakaan libxml2. Apakah libxml2 diinstal?" , coba lakukan ini dulu:

# 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

Validator paling sederhana

Mari buat validator.py paling sederhana

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

lalu tulis dan jalankan main.py

from validator import validate

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

Sedikit OOP

Untuk memvalidasi lebih dari satu file, tidak perlu membuat objek XMLSchema setiap saat, oleh karena itu:

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

Sekarang kita dapat memvalidasi semua file di direktori sebagai berikut:

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! :(')

Untuk opsi selengkapnya, baca di sini: Validasi dengan lxml

SergO
sumber
14

Paket PyXB di http://pyxb.sourceforge.net/ menghasilkan pengikatan validasi untuk Python dari dokumen skema XML. Ini menangani hampir setiap konstruksi skema dan mendukung banyak ruang nama.

pabigot.dll
sumber
12

Ada dua cara (sebenarnya ada lebih banyak) yang bisa Anda lakukan ini.
1. menggunakan 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. Gunakan xmllint dari baris perintah. xmllint sudah terpasang di banyak distribusi linux.

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

Komu
sumber
Saya memiliki 3 file xsd, hanya ketika semua 3 xsd ada saya dapat memvalidasi xml ... dapatkah ini dilakukan dengan metode Anda?
Naveen
9

Anda dapat dengan mudah memvalidasi file atau pohon XML terhadap XML Schema (XSD) dengan paket xmlschema Python . Ini murni Python, tersedia di PyPi dan tidak memiliki banyak dependensi.

Contoh - memvalidasi file:

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

Metode ini memunculkan pengecualian jika file tidak divalidasi terhadap XSD. Pengecualian itu kemudian berisi beberapa detail pelanggaran.

Jika Anda ingin memvalidasi banyak file, Anda hanya perlu memuat XSD sekali:

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

Jika Anda tidak memerlukan pengecualian, Anda dapat memvalidasi seperti ini:

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

Atau, xmlschema langsung bekerja pada objek file dan pohon XML memori (baik dibuat dengan xml.etree.ElementTree atau lxml). Contoh:

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