Анализ XML-файлов и проверка по схеме xsd
Это пример вывода XML, который мне нужно проанализировать и проверить на соответствие файлам схемы xsd.
<Record_Delimiter DocumentID="1.1" DocumentType="PARENT" DocumentName="SCHOOL" RelatedDocumentID=""/>
<xs:SCHOOL>
<xs:Name>some name</xs:Name>
<xs:ID>5908390481</xs:ID>
<xs:Address>some address</xs:Address>
</xs:SCHOOL>
<Record_Delimiter DocumentID="1.2" DocumentType="CHILD" DocumentName="STUDENTEXP" RelatedDocumentID="1.1"/>
<xs:STUDENTEXP>
<xs:STUDENT>
<xs:Name>some name</xs:Name>
<xs:SID>s1036456</xs:SID>
<xs:Age>12</xs:Age>
<xs:Address>some address</xs:Address>
<xs:Expenses>
<xs:Fees>800</xs:Fees>
<xs:Books>100</xs:Books>
<xs:Uniform>50</xs:Uniform>
<xs:Transport>10</xs:Transport>
</xs:Expenses>
</xs:STUDENT>
</xs:STUDENTEXP>
<Record_Delimiter DocumentID="1.3" DocumentType="CHILD" DocumentName="STUDENTEXP" RelatedDocumentID="1.1"/>
<xs:STUDENTEXP>
<xs:STUDENT>
<xs:Name>some name</xs:Name>
<xs:SID>s1036789</xs:SID>
<xs:Age>15</xs:Age>
<xs:Address>some address</xs:Address>
<xs:Expenses>
<xs:Fees>1000</xs:Fees>
<xs:Books>200</xs:Books>
<xs:Uniform>50</xs:Uniform>
<xs:Transport>10</xs:Transport>
</xs:Expenses>
</xs:STUDENT>
</xs:STUDENTEXP>
Сам этот файл не является допустимым XML, потому что нет единого тега, охватывающего все остальные теги. Но каждая запись (например, SCHOOL и STUDENTEXP) является допустимым XML и проверяется на соответствие схеме (school.xsd, studentexp.xsd).
Я никогда не работал с этим форматом и не уверен в некоторых вещах, например, как программно разобрать такой файл? Обычно, используя lxml, мы можем проверить каждую запись, если она была в отдельном файле:
xmlschema = etree.XMLSchema(etree.parse('./studentexp.xsd'))
xmlschema.assertValidate(etree.parse('./sampleStudentexp.xml'))
Как правильно извлекать "записи" и проверять их отдельно?
2 ответа
Этот вопрос задавался раньше: проанализировать XML-файл с несколькими корневыми элементами в python
Я подозреваю, что существует однопроходное решение, предполагающее использование парсера потока. Мой Python недостаточно силен, чтобы понять, возможно ли это. В любом случае - одно из решений в этой ветке может быть достаточно хорошим.
Lxml имеет парсинг событий на основе тегов. инкрементальный анализ событий и ниже работало.
parser = etree.XMLPullParser(events=('start', 'end'))
events = parser.read_events()
with open('.\sample.xml', 'rb') as f:
d1 = deque()
for line in f:
parser.feed(line)
for action, e in events:
if action == 'start':
d1.append(e.tag)
elif action == 'end' and len(d1) == 1:
if d1.pop() == e.tag:
root = parser.close()
print(etree.tostring(root, pretty_print=True, encoding="UTF-8").decode("UTF-8"))
else:
d1.pop()