Проверка Schematron с помощью lxml в Python: как получить ошибки проверки?
Я пытаюсь сделать некоторые проверки Schematron с lxml. Для конкретного приложения, над которым я работаю, важно, чтобы о любых тестах, которые не прошли проверку, сообщалось. В документации lxml упоминается наличие validation_report
объект недвижимости. Я думаю, что это должно содержать информацию, которую я ищу, но я просто не могу понять, как с ней работать. Вот пример кода, который демонстрирует мою проблему (адаптировано из http://lxml.de/validation.html; протестировано с Python 2.7.4):
import StringIO
from lxml import isoschematron
from lxml import etree
def main():
# Schema
f = StringIO.StringIO('''\
<schema xmlns="http://purl.oclc.org/dsdl/schematron" >
<pattern id="sum_equals_100_percent">
<title>Sum equals 100%.</title>
<rule context="Total">
<assert test="sum(//Percent)=100">Sum is not 100%.</assert>
</rule>
</pattern>
</schema>
''')
# Parse schema
sct_doc = etree.parse(f)
schematron = isoschematron.Schematron(sct_doc, store_report = True)
# XML to validate - validation will fail because sum of numbers
# not equal to 100
notValid = StringIO.StringIO('''\
<Total>
<Percent>30</Percent>
<Percent>30</Percent>
<Percent>50</Percent>
</Total>
''')
# Parse xml
doc = etree.parse(notValid)
# Validate against schema
validationResult = schematron.validate(doc)
# Validation report (assuming here this is where reason
# for validation failure is stored, but perhaps I'm wrong?)
report = isoschematron.Schematron.validation_report
print("is valid: " + str(validationResult))
print(dir(report.__doc__))
main()
Теперь от значения validationResult
Я вижу, что проверка не удалась (как и ожидалось), поэтому в следующий раз я хотел бы знать, почему. Результат второго оператора печати дает мне:
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__
format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__get
slice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mo
d__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook
__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center',
'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index
', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper',
'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', '
rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', '
strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']
Который о том, насколько я получаю, основываясь на документации и этом связанном вопросе. Может быть, что-то действительно очевидное я пропускаю?
1 ответ
Итак, кто-то в Твиттере дал мне предложение, которое заставило меня понять, что я ошибочно понял ссылку на класс schematron. Поскольку нет четких примеров, я поделюсь своим рабочим решением ниже:
import StringIO
from lxml import isoschematron
from lxml import etree
def main():
# Example adapted from http://lxml.de/validation.html#id2
# Schema
f = StringIO.StringIO('''\
<schema xmlns="http://purl.oclc.org/dsdl/schematron" >
<pattern id="sum_equals_100_percent">
<title>Sum equals 100%.</title>
<rule context="Total">
<assert test="sum(//Percent)=100">Sum is not 100%.</assert>
</rule>
</pattern>
</schema>
''')
# Parse schema
sct_doc = etree.parse(f)
schematron = isoschematron.Schematron(sct_doc, store_report = True)
# XML to validate - validation will fail because sum of numbers
# not equal to 100
notValid = StringIO.StringIO('''\
<Total>
<Percent>30</Percent>
<Percent>30</Percent>
<Percent>50</Percent>
</Total>
''')
# Parse xml
doc = etree.parse(notValid)
# Validate against schema
validationResult = schematron.validate(doc)
# Validation report
report = schematron.validation_report
print("is valid: " + str(validationResult))
print(type(report))
print(report)
main()
Оператор печати в отчете теперь приводит к следующему выводу:
<?xml version="1.0" standalone="yes"?>
<svrl:schematron-output xmlns:svrl="http://purl.oclc.org/dsdl/svrl" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:schold="http://www.ascc.net/xml/schematron" xmlns:sch="http://www.ascc.net/xml/schematron" xmlns:iso="http://purl.oclc.org/dsdl/schematron" title="" schemaVersion="">
<!--
-->
<svrl:active-pattern id="sum_equals_100_percent" name="Sum equals 100%."/>
<svrl:fired-rule context="Total"/>
<svrl:failed-assert test="sum(//Percent)=100" location="/Total">
<svrl:text>Sum is not 100%.</svrl:text>
</svrl:failed-assert>
</svrl:schematron-output>
Что именно то, что я искал!