【问题标题】:How do I skip validating global declaration issues in lxml?如何跳过验证 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

标签: python lxml


【解决方案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

    您也许可以从接下来的内容中判断出来,但是每次遇到问题时,您都必须回溯到每个决定,并在那个时候尝试另一个决定。

    这很快就会变得非常复杂,因为某些东西是否有效可能取决于它的内容、结构、属性值等。很快,你就会有很多选项来测试它变得不可能——你甚至可以想到选择的数量实际上是无限的情况,因此您必须包含非常复杂的逻辑才能得出有效值。

    在简单的情况下,例如您展示的示例,其中只有外部标记可能被错误命名,您可以简单地在内存中修复该错误并重试验证。但这不是一种适用于整个文档的方法。

    注意:在现实生活场景中,您实际上可能知道并预期会发生什么,您可以遵循尝试验证的策略,如果验证失败,则重复解决问题,因为您确实知道选项是,直到您到达文档的末尾。我的回答只是想说明这里没有通用的解决方案。

    【讨论】:

      猜你喜欢
      • 2013-09-12
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多