如何跳过验证 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 中的全局声明问题?的主要内容,如果未能解决你的问题,请参考以下文章

机跳过Google验证

java 调用WebService如何跳过安全证书验证的问题

如何跳过谷歌验证

如何在 Python 中针对 DTD 文件验证 xml

单击特定按钮时如何跳过验证?

如何跳过软件登陆界面