Python'da bir XML şemasıyla doğrulama


104

Bir XML dosyam ve başka bir dosyada bir XML şemam var ve XML dosyamın şemaya uyduğunu doğrulamak istiyorum. Bunu Python'da nasıl yaparım?

Standart kitaplığı kullanan bir şeyi tercih ederim, ancak gerekirse üçüncü taraf bir paket kurabilirim.

Yanıtlar:


61

XSD dosyalarını kullanmayı kastettiğinizi varsayıyorum. Şaşırtıcı bir şekilde, bunu destekleyen pek çok python XML kitaplığı yok. lxml bunu yapar. Lxml ile Doğrulamayı kontrol edin . Sayfa ayrıca, diğer şema türleriyle doğrulama yapmak için lxml'nin nasıl kullanılacağını da listeler.


1
lxml saf python mu değil mi? (derleme / kurulum gerektirir ya da sadece python komut dosyalarınıza ekleyebilirsiniz)
sorin

9
@Sorin: lxml, libxml2 C kitaplığının üstündeki bir sarmalayıcıdır ve bu nedenle saf Python değildir.
Eli Courtwright

2
@eli Tam olarak altını çizmek istediğim şey, bu hiç kimse için uygun olmayabilir.
sorin

1
Doğrulama hataları kullanıcı dostu değildir. Bunu nasıl yapacağım? mailman-mail5.webfaction.com/pipermail/lxml/2012-April/… yardımcı olmuyor.
Hiçbiri

Bu cevap hala güncel mi?
İnsan

27

"Saf python" çözümlerine gelince: paket dizini şunları listeler:

  • pyxsd , açıklama, "saf python" olmayan (ancak stdlib'e dahil olan) xml.etree.cElementTree'yi kullandığını söylüyor, ancak kaynak kodu, xml.etree.ElementTree'ye geri döndüğünü gösteriyor, bu nedenle bu, saf python olarak sayılır. Kullanmadım, ancak belgelere göre şema doğrulaması yapıyor.
  • minixsv : '"saf" Python ile yazılmış hafif bir XML şeması doğrulayıcı. Bununla birlikte, açıklamada "şu anda XML şema standardının bir alt kümesi destekleniyor" diyor, bu nedenle bu yeterli olmayabilir.
  • W3C'nin çevrimiçi xsd doğrulayıcısı için kullanıldığını düşündüğüm XSV (hala korunmadığını düşündüğüm eski pyxml paketini kullanıyor gibi görünüyor)

5
Bunlardan PyXB'ye bir göz atardım. Görünüşe göre bunların çoğu eksik kalıyor ve bir şekilde "ölü" görünüyorlar. pyxsd en son 2006'da güncellendi, minixsv en son 2008'de, XSV ise anlayabildiğim kadarıyla 2007'de. Bir paketi diğerinin üzerinde düşünmek için her zaman en iyi neden bu değildir, ancak bu durumda haklı olduğunu düşünüyorum.
oob

2
PyXB için +1. Admin bölümüne eklenen ham XML'i doğrulamak için Django'da kullanıyorum. Basit ve kullanımı kolay.
tatlar

21

Popüler lxml kitaplığını kullanan Python3'te basit bir doğrulayıcı örneği

Kurulum lxml

pip install lxml

"XmlCheckVersion işlevi libxml2 kitaplığında bulunamadı. Libxml2 yüklü mü?" Gibi bir hata alırsanız , önce bunu yapmayı deneyin:

# 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

En basit doğrulayıcı

En basit validator.py oluşturalım

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

sonra main.py yazın ve çalıştırın

from validator import validate

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

Biraz OOP

Birden fazla dosyayı doğrulamak için, her seferinde bir XMLSchema nesnesi oluşturmaya gerek yoktur , bu nedenle:

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

Şimdi dizindeki tüm dosyaları şu şekilde doğrulayabiliriz:

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

Daha fazla seçenek için burayı okuyun: lxml ile doğrulama



12

Bunu yapmanın iki yolu var (aslında daha fazlası var).
1. lxml kullanarak
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. Komut satırından xmllint kullanın . xmllint birçok linux dağıtımında yüklü olarak gelir.

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


3 xsd dosyam var, ancak 3 xsd'nin tümü mevcut olduğunda bir xml'yi doğrulayabilirim ... bu sizin yönteminizle yapılabilir mi?
Naveen

9

Xmlschema Python paketi ile bir XML dosyasını veya ağacı bir XML Şemasına (XSD) göre kolayca doğrulayabilirsiniz . PyPi'de bulunan saf Python'dur ve pek fazla bağımlılığı yoktur.

Örnek - bir dosyayı doğrulayın:

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

Dosya XSD'ye göre doğrulanmazsa, yöntem bir istisna oluşturur. Bu istisna, daha sonra bazı ihlal ayrıntılarını içerir.

Birçok dosyayı doğrulamak istiyorsanız, XSD'yi yalnızca bir kez yüklemeniz gerekir:

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

İstisnaya ihtiyacınız yoksa, şu şekilde doğrulayabilirsiniz:

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

Alternatif olarak, xmlschema doğrudan dosya nesneleri üzerinde ve bellek XML ağaçlarında (xml.etree.ElementTree veya lxml ile oluşturulmuş) çalışır. Misal:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.