Source code for ocrd_validators.xsd_validator
"""
Validating XML Schema
"""
from pathlib import Path
from lxml import etree as ET
from ocrd_models import ValidationReport
from .constants import XSD_PATHS
#
# -------------------------------------------------
#
[docs]
class XsdValidator():
"""
XML Schema validator.
"""
_instances = {}
[docs]
@classmethod
def instance(cls, schema_url):
if schema_url in cls._instances:
return cls._instances[schema_url]
cls._instances[schema_url] = cls(schema_url)
return cls._instances[schema_url]
[docs]
@classmethod
def validate(cls, schema_url, doc):
"""
Validate an XML document against a schema.
Args:
doc (etree.ElementTree|str|bytes):
schema_url (str): URI of XML schema to validate against.
"""
return cls.instance(schema_url)._validate(doc) # pylint: disable=protected-access
def __init__(self, schema_url):
"""
Construct an XsdValidator.
Args:
schema_url (str): URI of XML schema to validate against.
"""
if schema_url not in XSD_PATHS:
raise Exception('XML schema not bundled with OCR-D: %s' % schema_url)
with open(XSD_PATHS[schema_url], 'r') as f:
xmlschema_doc = ET.parse(f)
self._xmlschema = ET.XMLSchema(xmlschema_doc)
def _validate(self, doc):
"""
Do the actual validation.
Arguments:
doc (etree.ElementTree|str|bytes|pathlib.Path): the document. if etree: us as-is. if str/bytes: parse as XML string. If Path: read_text on it
Returns: ValidationReport
"""
report = ValidationReport()
if isinstance(doc, Path):
doc = ET.parse(str(doc))
if isinstance(doc, (bytes, str)):
doc = ET.fromstring(doc)
try:
self._xmlschema.assertValid(doc)
except ET.DocumentInvalid as fail:
for err in fail.error_log: # pylint: disable=no-member
report.add_error("Line %s: %s" % (err.line, err.message))
return report