ตรวจสอบความถูกต้องด้วย XML schema ใน Python


104

ฉันมีไฟล์ XML และสคีมา XML ในไฟล์อื่นและฉันต้องการตรวจสอบว่าไฟล์ XML ของฉันเป็นไปตามสคีมา ฉันจะทำสิ่งนี้ใน Python ได้อย่างไร

ฉันต้องการบางอย่างโดยใช้ไลบรารีมาตรฐาน แต่ฉันสามารถติดตั้งแพ็คเกจของบุคคลที่สามได้หากจำเป็น

คำตอบ:


61

ฉันสมมติว่าคุณหมายถึงใช้ไฟล์ XSD น่าแปลกที่มีไลบรารี python XML ไม่มากนักที่รองรับสิ่งนี้ lxml ทำอย่างไรก็ตาม ตรวจสอบการตรวจสอบกับ lxml หน้านี้ยังแสดงวิธีใช้ lxml เพื่อตรวจสอบความถูกต้องกับสคีมาประเภทอื่น ๆ


1
lxml เป็น python ล้วนๆหรือเปล่า? (ต้องการการรวบรวม / การติดตั้งหรือคุณสามารถรวมไว้กับสคริปต์ python ของคุณ)
sorin

9
@Sorin: lxml เป็นกระดาษห่อหุ้มที่อยู่ด้านบนของไลบรารี libxml2 C ดังนั้นจึงไม่ใช่ Python ที่บริสุทธิ์
Eli Courtwright

2
@eli สิ่งที่ฉันต้องการขีดเส้นใต้สิ่งนี้อาจไม่เหมาะสมสำหรับทุกคน
ซอริน

1
ข้อผิดพลาดในการตรวจสอบไม่เป็นมิตรกับผู้ใช้ ฉันจะไปเกี่ยวกับเรื่องนั้นได้อย่างไร? mailman-mail5.webfaction.com/pipermail/lxml/2012-April/…ไม่ช่วย
ไม่มี - ดา

คำตอบนี้ยังคงเป็นปัจจุบันอยู่หรือไม่?
มนุษย์

27

สำหรับโซลูชัน "pure python": รายการดัชนีแพ็คเกจ:

  • pyxsdคำอธิบายระบุว่าใช้ xml.etree.cElementTree ซึ่งไม่ใช่ "python บริสุทธิ์" (แต่รวมอยู่ใน stdlib) แต่ซอร์สโค้ดระบุว่ามันกลับไปเป็น xml.etree.ElementTree ดังนั้นสิ่งนี้จะนับเป็น python ที่บริสุทธิ์ ยังไม่ได้ใช้ แต่ตามเอกสารจะทำการตรวจสอบสคีมา
  • minixsv : 'โปรแกรมตรวจสอบสคีมา XML ที่มีน้ำหนักเบาซึ่งเขียนด้วย "pure" Python " อย่างไรก็ตามคำอธิบายระบุว่า "ปัจจุบันรองรับชุดย่อยของมาตรฐานสคีมา XML" ดังนั้นจึงอาจไม่เพียงพอ
  • XSVซึ่งฉันคิดว่าใช้สำหรับโปรแกรมตรวจสอบ xsd ออนไลน์ของ W3C (ดูเหมือนว่าจะใช้แพ็คเกจ pyxml เก่าซึ่งฉันคิดว่าไม่ได้รับการดูแลอีกต่อไป)

5
ฉันจะดู PyXB เกี่ยวกับสิ่งเหล่านี้ ดูเหมือนสถานะเหล่านี้ส่วนใหญ่จะไม่สมบูรณ์และดูเหมือน "ตาย" อยู่บ้าง pyxsd อัปเดตล่าสุดในปี 2549 minixsv อัปเดตล่าสุดในปี 2008 XSV ในปี 2550 เท่าที่ฉันสามารถบอกได้ ไม่ใช่เหตุผลที่ดีที่สุดเสมอไปในการพิจารณาแพ็คเกจหนึ่งมากกว่าอีกแพ็คเกจหนึ่ง แต่ฉันคิดว่ามันสมเหตุสมผลในกรณีนี้
oob

2
+1 สำหรับ PyXB ฉันใช้มันใน Django เพื่อตรวจสอบความถูกต้องของ XML ดิบที่แทรกในส่วนผู้ดูแลระบบ ง่ายและใช้งานง่าย
tatlar

21

ตัวอย่างของตัวตรวจสอบความถูกต้องอย่างง่ายใน Python3 โดยใช้ไลบรารียอดนิยมlxml

การติดตั้ง lxml

pip install lxml

หากคุณได้รับข้อผิดพลาดเช่น"ไม่พบฟังก์ชัน xmlCheckVersion ในไลบรารี libxml2 มีการติดตั้ง libxml2 หรือไม่" ให้ลองทำสิ่งนี้ก่อน:

# 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.py ที่ง่ายที่สุด

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

จากนั้นเขียนและเรียกใช้main.py

from validator import validate

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

OOP เล็กน้อย

ในการตรวจสอบความถูกต้องมากกว่าหนึ่งไฟล์คุณไม่จำเป็นต้องสร้างอ็อบเจ็กต์XMLSchemaทุกครั้งดังนั้น:

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

ตอนนี้เราสามารถตรวจสอบไฟล์ทั้งหมดในไดเร็กทอรีได้ดังนี้:

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

สำหรับตัวเลือกเพิ่มเติมโปรดอ่านที่นี่: การตรวจสอบความถูกต้องด้วย lxml


14

แพคเกจ PyXB ที่http://pyxb.sourceforge.net/สร้างการตรวจสอบการเชื่อมโยงสำหรับ Python จากเอกสาร XML schema จัดการโครงสร้างสคีมาเกือบทั้งหมดและรองรับหลายเนมสเปซ


12

มีสองวิธี (จริงๆแล้วมีมากกว่านั้น) ที่คุณสามารถทำได้
1. ใช้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. ใช้xmllintจาก commandline xmllint มาติดตั้งในลินุกซ์หลายรุ่น

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


ฉันมีไฟล์ xsd 3 ไฟล์เฉพาะเมื่อมี xsd ทั้ง 3 อยู่ฉันสามารถตรวจสอบ xml ได้ ... สามารถทำได้ด้วยวิธีของคุณหรือไม่?
Naveen

9

คุณสามารถตรวจสอบไฟล์ XML หรือต้นไม้กับ XML Schema (XSD) กับxmlschema แพคเกจหลาม เป็น Python แท้พร้อมใช้งานบนPyPiและไม่มีการอ้างอิงมากนัก

ตัวอย่าง - ตรวจสอบไฟล์:

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

วิธีนี้ทำให้เกิดข้อยกเว้นหากไฟล์ไม่ได้รับการตรวจสอบความถูกต้องกับ XSD ข้อยกเว้นนั้นจะมีรายละเอียดการละเมิดบางอย่าง

หากคุณต้องการตรวจสอบไฟล์จำนวนมากคุณต้องโหลด XSD เพียงครั้งเดียว:

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

หากคุณไม่ต้องการข้อยกเว้นคุณสามารถตรวจสอบได้ดังนี้:

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

หรืออีกวิธีหนึ่งคือ xmlschema ทำงานโดยตรงกับอ็อบเจ็กต์ไฟล์และในทรี XML ของหน่วยความจำ (สร้างด้วย xml.etree.ElementTree หรือ lxml) ตัวอย่าง:

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.