如何跳过验证 lxml 中的全局声明问题?
Posted
技术标签:
【中文标题】如何跳过验证 lxml 中的全局声明问题?【英文标题】:How do I skip validating global declaration issues in lxml? 【发布时间】:2022-01-19 02:31:06 【问题描述】:我怎样才能跳过Element 'baz': No matching global declaration available for the validation root., line 1
这个错误?
我需要验证一组通用的 XML/XSD 对,它们不一定以任何方式相似地组成,因此适用于特定 XML 结构的硬编码/文字规则不适用。
XSD 由 GMC Inspire Designer 生成,它通常不是 XML 验证器,并且在检查语法方面非常“松散”。全局声明问题出现在我的本地验证器中,但在 Inspire Designer 中没有出现,因为它的松散性质。
如何针对lxml
生成的特定错误集指定并继续验证?
使用以下代码:
#get a list of all files in the working directory that are .xml files
xml_files_from_cwd = [xml_f for xml_f in listdir(my_path) if isfile(join(my_path, xml_f))
and xml_f.lower().endswith(".xml")]
xml_validator = etree.XMLSchema(file= my_path)
for xml in xml_files_from_cwd:
recovering_parser = etree.XMLParser(recover=True)
xml_file = etree.parse(my_path + "/" +xml, parser=recovering_parser)
successful = False
try:
successful = xml_validator.assertValid(xml_file)
except Exception as e:
print(f"File not valid: e")
if successful:
print(f"No errors detected in xml.")
我在验证 XML 文件所在的位置时遇到问题,通常如下所示:
<baz>
<bar BEGIN="1">
... [repeating elements here]
</bar>
</baz>
还有一个遵循这种格式的 XSD:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="foo">
<xsd:complexType>
<xsd:sequence minOccurs="1" maxOccurs="1">
<xsd:element name="bar" minOccurs="1" maxOccurs="unbounded">
.... [repeating elements here]
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
【问题讨论】:
我是否正确理解您的文档实际上是无效的('baz' 外部元素而不是 'foo'),但除此之外它可能是有效的,并且您希望验证器只报告还有什么问题吗?在加载之后但在验证之前简单地将外部元素从“baz”更改为“foo”怎么样? @Grismar 你是对的 - 这将在单一上下文中工作,但是由于涉及的实现数量,对任何单一文件实现进行抽查将浪费大量时间/额外工作。除非您建议我将结构一层一层地剥离,直到它验证?老实说,我只需要它继续验证直到文件结束并找出所有可能的问题。 问题在于,您提出的建议可能适用于简单的问题,例如命名错误的元素,但是如果完全缺少 'baz' 或者如果有替代 'foo' 的位置怎么办。验证必须在第一个错误时停止,因为根据有关如何修复错误的选择(如果有意义的话),随后的任何内容可能有效也可能无效。在这个微不足道的情况下不是那么多,但绝对是一般的。 @Grismar 我听到了。这确实是一个问题,因为 Inspire Designer 在文件失败时不会产生任何错误上下文,并且在结果的方法/一致性方面似乎表现得相当不规则。命名空间和一些属性似乎会虚假地导致问题。当我无法访问逻辑本身时,试图找到一个合适的解决方案。 如果你想把它扔进答案,我会把它标记为完整的,就是这样。 @Grismar 【参考方案1】:对于“我们能否在初始失败条件后继续验证文件”这个问题的答案似乎是否定的,因为除了简单/琐碎的情况之外,无法保证任何进一步的验证是否会产生积极的结果。
【讨论】:
【参考方案2】:这里的问题是验证依赖于整个文档是有效的。
例如,如果您的文件适用于:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="foo">
<xs:complexType>
<xs:choice>
<xs:element name="bar">
<xs:complexType>
<xs:choice>
<xs:element name="baz"/>
<xs:element name="qux"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="quux">
<xs:complexType>
<xs:sequence>
<xs:element name="qux"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
这个文件会有问题:
<foo>
<quuz>
<qux/>
...
</quuz>
</foo>
quuz
应该是 bar
还是 quux
?
您也许可以从接下来的内容中判断出来,但是每次遇到问题时,您都必须回溯到每个决定,并在那个时候尝试另一个决定。
这很快就会变得非常复杂,因为某些东西是否有效可能取决于它的内容、结构、属性值等。很快,你就会有很多选项来测试它变得不可能——你甚至可以想到选择的数量实际上是无限的情况,因此您必须包含非常复杂的逻辑才能得出有效值。
在简单的情况下,例如您展示的示例,其中只有外部标记可能被错误命名,您可以简单地在内存中修复该错误并重试验证。但这不是一种适用于整个文档的方法。
注意:在现实生活场景中,您实际上可能知道并预期会发生什么,您可以遵循尝试验证的策略,如果验证失败,则重复解决问题,因为您确实知道选项是,直到您到达文档的末尾。我的回答只是想说明这里没有通用的解决方案。
【讨论】:
以上是关于如何跳过验证 lxml 中的全局声明问题?的主要内容,如果未能解决你的问题,请参考以下文章