ฉันมีไฟล์ XML และสคีมา XML ในไฟล์อื่นและฉันต้องการตรวจสอบว่าไฟล์ XML ของฉันเป็นไปตามสคีมา ฉันจะทำสิ่งนี้ใน Python ได้อย่างไร
ฉันต้องการบางอย่างโดยใช้ไลบรารีมาตรฐาน แต่ฉันสามารถติดตั้งแพ็คเกจของบุคคลที่สามได้หากจำเป็น
ฉันมีไฟล์ XML และสคีมา XML ในไฟล์อื่นและฉันต้องการตรวจสอบว่าไฟล์ XML ของฉันเป็นไปตามสคีมา ฉันจะทำสิ่งนี้ใน Python ได้อย่างไร
ฉันต้องการบางอย่างโดยใช้ไลบรารีมาตรฐาน แต่ฉันสามารถติดตั้งแพ็คเกจของบุคคลที่สามได้หากจำเป็น
คำตอบ:
ฉันสมมติว่าคุณหมายถึงใช้ไฟล์ XSD น่าแปลกที่มีไลบรารี python XML ไม่มากนักที่รองรับสิ่งนี้ lxml ทำอย่างไรก็ตาม ตรวจสอบการตรวจสอบกับ lxml หน้านี้ยังแสดงวิธีใช้ lxml เพื่อตรวจสอบความถูกต้องกับสคีมาประเภทอื่น ๆ
สำหรับโซลูชัน "pure python": รายการดัชนีแพ็คเกจ:
การติดตั้ง 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
แพคเกจ PyXB ที่http://pyxb.sourceforge.net/สร้างการตรวจสอบการเชื่อมโยงสำหรับ Python จากเอกสาร XML schema จัดการโครงสร้างสคีมาเกือบทั้งหมดและรองรับหลายเนมสเปซ
มีสองวิธี (จริงๆแล้วมีมากกว่านั้น) ที่คุณสามารถทำได้
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')
>> xmllint --format --pretty 1 --load-trace --debug --schema /path/to/my_schema_file.xsd /path/to/my_xml_file.xml
คุณสามารถตรวจสอบไฟล์ 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))
lxml ให้ etree.DTD
จากการทดสอบบนhttp://lxml.de/api/lxml.tests.test_dtd-pysrc.html
...
root = etree.XML(_bytes("<b/>"))
dtd = etree.DTD(BytesIO("<!ELEMENT b EMPTY>"))
self.assert_(dtd.validate(root))