使用Schema验证XML失败,但读取写入文件后验证成功
问题描述
我用lxml工具验证XML内容,通过Python代码构造了带TEI命名空间的XML结构:
tei = etree.Element("TEI", nsmap={None: 'http://www.tei-c.org/ns/1.0'})
随后用指定XSD文件验证时,执行以下代码:
xmlschema_doc = etree.parse(xsd_file_path) xmlschema = etree.XMLSchema(xmlschema_doc) # 执行检查 status = xmlschema.validate(xml_tree)
返回False,错误信息为:Element 'TEI': No matching global declaration available for the validation root.
但出现一个特殊情况:如果把XML写入文件:
ET = etree.ElementTree(xmlData) ET.write('test.xml', pretty_print=True, xml_declaration=True, encoding='utf-8')
再用b= etree.parse('test.xml')读取文件,执行xmlschema.validate(b)就能验证通过,说明XML结构本身合法。
请问需要在XML结构中添加什么内容来解决这个问题?
补充信息:
- 未验证通过的XML开头:
<TEI xmlns="http://www.tei-c.org/ns/1.0"> - 验证通过的XML文件开头:
<?xml version='1.0' encoding='UTF-8'?><TEI xmlns="http://www.tei-c.org/ns/1.0">
完整XML示例:
<?xml version='1.0' encoding='UTF-8'?> <TEI xmlns="http://www.tei-c.org/ns/1.0"> <text> <body> <listBibl> <biblFull> <titleStmt> <title xml:lang="en">article</title> <title xml:lang="fr">article</title> <title type="sub" xml:lang="en">A subtitle</title> <author role="aut"> <persName> <forename type="first">John</forename> <surname>Doe</surname> </persName> <email>email</email> <idno type="http://orcid.org/">orcid</idno> <affiliation ref="#localStruct-affiliation"/> <affiliation ref="#struct-affiliation"/> </author> <author role="aut"> <persName> <forename type="first">Jane</forename> <forename type="middle">Middle</forename> <surname>Doe</surname> </persName> <email>email</email> <idno type="http://orcid.org/">orcid</idno> <affiliation ref="#localStruct-affiliationA"/> <affiliation ref="#localStruct-affiliationB"/> </author> </titleStmt> <editionStmt> <edition> <ref type="file" subtype="author" n="1" target="upload.pdf"/> </edition> </editionStmt> <publicationStmt> <availability> <licence target="https://creativecommons.org/licenses//cc-by/"/> </availability> </publicationStmt> <notesStmt> <note type="audience" n="2"/> <note type="invited" n="1"/> <note type="popular" n="0"/> <note type="peer" n="1"/> <note type="proceedings" n="0"/> <note type="commentary">small comment</note> <note type="description">small description</note> </notesStmt> <sourceDesc> <biblStruct> <analytic> <title xml:lang="en">article</title> <title xml:lang="fr">article</title> <title type="sub" xml:lang="en">A subtitle</title> <author role="aut"> <persName> <forename type="first">John</forename> <surname>Doe</surname> </persName> <email>email</email> <idno type="http://orcid.org/">orcid</idno> <affiliation ref="#localStruct-affiliation"/> <affiliation ref="#struct-affiliation"/> </author> <author role="aut"> <persName> <forename type="first">Jane</forename> <forename type="middle">Middle</forename> <surname>Doe</surname> </persName> <email>email</email> <idno type="http://orcid.org/">orcid</idno> <affiliation ref="#localStruct-affiliationA"/> <affiliation ref="#localStruct-affiliationB"/> </author> </analytic> <monogr> <idno type="isbn">978-1725183483</idno> <idno type="halJournalId">117751</idno> <idno type="issn">xxx</idno> <imprint> <publisher>springer</publisher> <biblScope unit="serie">a special collection</biblScope> <biblScope unit="volume">20</biblScope> <biblScope unit="issue">1</biblScope> <biblScope unit="pp">10-25</biblScope> <date type="datePub">2024-01-01</date> </imprint> </monogr> <series/> <idno type="doi">reg</idno> <idno type="arxiv">ger</idno> <idno type="bibcode">erg</idno> <idno type="ird">greger</idno> <idno type="pubmed">greger</idno> <idno type="ads">gaergezg</idno> <idno type="pubmedcentral">gegzefdv</idno> <idno type="irstea">vvxc</idno> <idno type="sciencespo">gderg</idno> <idno type="oatao">gev</idno> <idno type="ensam">xcvcxv</idno> <idno type="prodinra">vxcv</idno> <ref type="publisher">https://publisher.com/ID</ref> <ref type="seeAlso">https://link1.com/ID</ref> <ref type="seeAlso">https://link2.com/ID</ref> <ref type="seeAlso">https://link3.com/ID</ref> </biblStruct> </sourceDesc> <profileDesc> <textClass> <keywords scheme="author"> <term xml:lang="en">keyword1</term> <term xml:lang="en">keyword2</term> <term xml:lang="fr">mot-clé1</term> <term xml:lang="fr">mot-clé2</term> </keywords> <classCode scheme="halDomain" n="physics"/> <classCode scheme="halDomain" n="halDomain2"/> <classCode scheme="halTypology" n="ART"/> </textClass> </profileDesc> </biblFull> </listBibl> </body> <back> <listOrg type="structures"> <org type="institution" xml:id="localStruct-affiliation"> <orgName>laboratory for MC, university of Yeah</orgName> <orgName type="acronym">LMC</orgName> <desc> <address> <addrLine>Blue street 155, 552501 Olso, Norway</addrLine> <country key="LS">Lesotho</country> </address> <ref type="url" target="https://lmc.univ-yeah.com"/> </desc> </org> <org type="institution" xml:id="localStruct-affiliationB"> <orgName>laboratory for MCL, university of Yeah</orgName> <orgName type="acronym">LMCL</orgName> <desc> <address> <addrLine>Blue street 155, 552501 Olso, Norway</addrLine> <country key="NO">Norway</country> </address> <ref type="url" target="https://lmcl.univ-yeah.com"/> </desc> </org> </listOrg> </back> </text> </TEI>
解决方案
问题核心是内存中构造的XML元素未正确绑定命名空间与全局元素声明的关联,写入文件再读取时lxml会重新解析并自动修正这个关联。不需要修改XML结构,只需调整构造或验证方式:
方法1:序列化后重新解析
把内存中的XML序列化为字符串,再解析成树结构后验证:
xml_str = etree.tostring(xml_tree, encoding='utf-8', xml_declaration=True) parsed_tree = etree.fromstring(xml_str) status = xmlschema.validate(parsed_tree)
方法2:确保子元素继承根元素命名空间
构造子元素时,不要直接用etree.Element("text"),而是通过根元素的makeelement方法创建,或显式指定命名空间,确保所有子元素都属于TEI命名空间:
# 方式1:用根元素的makeelement方法创建子元素 text = tei.makeelement("text") tei.append(text) # 方式2:显式指定命名空间 text = etree.Element("{http://www.tei-c.org/ns/1.0}text") tei.append(text)
如果之前构造子元素未指定命名空间,会导致子元素属于无命名空间,虽然根元素有命名空间,但XSD验证会判定结构不合法。写入文件再读取时,lxml会默认将无命名空间子元素归到根元素的默认命名空间下,因此验证通过。
方法3:用assertValid获取详细错误
若仍有问题,用xmlschema.assertValid(xml_tree)抛出详细异常,定位具体不符合命名空间要求的元素。
内容的提问来源于stack exchange,提问作者Guuk
相关产品推荐
相关产品推荐

