Xác thực bằng lược đồ XML trong Python


104

Tôi có một tệp XML và một lược đồ XML trong một tệp khác và tôi muốn xác thực rằng tệp XML của tôi có tuân theo lược đồ hay không. Làm cách nào để thực hiện việc này bằng Python?

Tôi muốn thứ gì đó sử dụng thư viện tiêu chuẩn, nhưng tôi có thể cài đặt gói của bên thứ ba nếu cần.

Câu trả lời:


61

Tôi cho rằng ý bạn là sử dụng các tệp XSD. Đáng ngạc nhiên là không có nhiều thư viện Python XML hỗ trợ điều này. Tuy nhiên, lxml thì không. Kiểm tra Xác thực bằng lxml . Trang này cũng liệt kê cách sử dụng lxml để xác thực với các loại lược đồ khác.


1
lxml có phải là mỡ trăn nguyên chất hay không? (không cần biên soạn / cài đặt hoặc bạn chỉ có thể bao gồm nó với kịch bản python của bạn)
Sorin

9
@Sorin: lxml là một trình bao bọc trên đầu thư viện libxml2 C và do đó không phải là Python thuần túy.
Eli Courtwright

2
@eli Chính xác những gì tôi muốn gạch dưới, điều này có thể không phù hợp với bất kỳ ai.
sorin

1
Lỗi xác thực không thân thiện với người dùng. Làm thế nào tôi sẽ đi về điều đó? mailman-mail5.web thoả mãn.com/pipermail/lxml/2012-April/… không giúp được gì.
Không có

Câu trả lời này có còn cập nhật không?
Nhân

27

Đối với các giải pháp "thuần túy python": chỉ mục gói liệt kê:

  • pyxsd , mô tả cho biết nó sử dụng xml.etree.cElementTree, không phải là "python thuần túy" (nhưng được bao gồm trong stdlib), nhưng mã nguồn cho biết rằng nó trở lại xml.etree.ElementTree, vì vậy điều này sẽ được tính là python thuần túy. Chưa sử dụng nó, nhưng theo tài liệu, nó thực hiện xác thực giản đồ.
  • minixsv : 'một trình xác thực lược đồ XML nhẹ được viết bằng Python "thuần túy". Tuy nhiên, mô tả cho biết "hiện tại một tập hợp con của tiêu chuẩn lược đồ XML được hỗ trợ", vì vậy điều này có thể không đủ.
  • XSV , mà tôi nghĩ được sử dụng cho trình xác thực xsd trực tuyến của W3C (có vẻ như nó vẫn sử dụng gói pyxml cũ, mà tôi cho rằng không còn được duy trì)

5
Tôi sẽ xem xét PyXB về những điều này. Có vẻ như hầu hết các trạng thái này chúng đều chưa hoàn thiện, và chúng có vẻ hơi "chết". pyxsd cập nhật lần cuối vào năm 2006, minixsv cập nhật lần cuối vào năm 2008, XSV năm 2007 theo như tôi có thể nói. Không phải lúc nào cũng là lý do tốt nhất để xem xét gói này hơn gói khác, nhưng tôi nghĩ nó là hợp lý trong trường hợp này.
oob,

2
+1 cho PyXB. Tôi đang sử dụng nó trong Django để xác thực XML thô được chèn trong phần Quản trị. Đơn giản và dễ sử dụng.
tatlar

21

Ví dụ về trình xác thực đơn giản trong Python3 sử dụng thư viện phổ biến lxml

Cài đặt lxml

pip install lxml

Nếu bạn gặp lỗi như "Không thể tìm thấy hàm xmlCheckVersion trong thư viện libxml2. Đã cài đặt libxml2 chưa?" , hãy thử làm điều này trước:

# 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

Trình xác thực đơn giản nhất

Hãy tạo validator.py đơn giản nhất

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

sau đó viết và chạy main.py

from validator import validate

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

Một chút OOP

Để xác thực nhiều hơn một tệp, không cần tạo đối tượng XMLSchema mọi lúc, do đó:

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

Bây giờ chúng ta có thể xác thực tất cả các tệp trong thư mục như sau:

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

Để biết thêm các tùy chọn, hãy đọc tại đây: Xác thực bằng lxml


14

Gói PyXB tại http://pyxb.sourceforge.net/ tạo các liên kết xác thực cho Python từ các tài liệu lược đồ XML. Nó xử lý hầu hết mọi cấu trúc lược đồ và hỗ trợ nhiều không gian tên.


12

Có hai cách (thực tế là có nhiều cách hơn) mà bạn có thể làm điều này.
1. sử dụng 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. Sử dụng xmllint từ dòng lệnh. xmllint được cài đặt trong nhiều bản phân phối linux.

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


Tôi có 3 tệp xsd, chỉ khi có cả 3 tệp xsd, tôi mới có thể xác thực một xml ... điều này có thể được thực hiện bằng phương pháp của bạn không?
Naveen

9

Bạn có thể dễ dàng xác thực một tệp hoặc cây XML dựa trên một Lược đồ XML (XSD) với gói xmlschema Python . Đó là Python thuần túy, có sẵn trên PyPi và không có nhiều phụ thuộc.

Ví dụ - xác thực một tệp:

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

Phương pháp này tạo ra một ngoại lệ nếu tệp không xác thực với XSD. Ngoại lệ đó sau đó chứa một số chi tiết vi phạm.

Nếu bạn muốn xác thực nhiều tệp, bạn chỉ phải tải XSD một lần:

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

Nếu bạn không cần ngoại lệ, bạn có thể xác thực như thế này:

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

Ngoài ra, xmlschema trực tiếp hoạt động trên các đối tượng tệp và trong cây XML bộ nhớ (được tạo bằng xml.etree.ElementTree hoặc lxml). Thí dụ:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.