【问题标题】:Parse several XML declarations in a single file by means of lxml.etree.iterparse通过 lxml.etree.iterparse 在一个文件中解析多个 XML 声明
【发布时间】:2011-04-13 14:52:18
【问题描述】:

我需要解析一个包含各种 XML 文件的文件,即 .. 等等。在使用 etree.iterparse 时,我收到以下(正确)错误:

lxml.etree.XMLSyntaxError: XML declaration allowed only at the start of the document

现在,我可以预处理输入文件并为每个包含的 XML 文件生成一个单独的文件。这可能是最简单的解决方案。但我想知道这个“问题”是否存在适当的解决方案。

谢谢!

【问题讨论】:

  • +1,我也遇到了同样的问题。您建议的解决方法是实现一个完整的 XML 解析器/扫描器,这超出了 lxml 的目的。
  • @larsmans:具有多个根元素的文件不是 XML 文档。不管你喜不喜欢,但不要怪 lxml。
  • @mzjn:我知道,但我每天都会遇到单个文件(或嵌入其他文件中的 XML)中的 XML 文档流。我不怪 lxml,但我会发现它是 XML 库能够处理它的一个很棒的特性。也许lxml可以做到,但我还没有找到它的开关。

标签: python xml lxml elementtree


【解决方案1】:

您提供的示例数据表明了一个问题,而您提供的问题和异常表明了另一个问题。您是否有多个连接在一起的 XML 文档,每个文档都有自己的 XML 声明,或者您是否有一个包含多个顶级元素的 XML 片段?

如果是前者,那么解决方案将涉及将输入流分解为多个流,并单独解析每个流。正如一条评论所暗示的,这并不一定意味着实现 XML 解析器。您可以在字符串中搜索 XML 声明,而无需解析其中的任何其他内容,只要您的输入不包括包含未转义 XML 声明的 CDATA 部分。您可以编写一个类似文件的对象,该对象从底层流返回字符,直到它遇到 XML 声明,然后将其包装在一个生成器函数中,该生成器函数不断返回流,直到到达 EOF。这不是微不足道的,但也不是非常困难。

如果您有一个包含多个顶级元素的 XML 片段,您可以将它们包装成一个 XML 元素并解析整个内容。

当然,与大多数涉及错误 XML 输入的问题一样,最简单的解决方案可能就是修复导致错误输入的问题。

【讨论】:

  • 感谢您的详细回答。我有前一个问题,这意味着连接了多个 XML 文档。不幸的是,我一开始就无法访问产生 XML 输出的代码,所以我必须处理那些格式不正确的伪 XML 文档。我喜欢你的想法,即使用一个生成器函数来返回流,直到达到 EOF。但是,我是 Python 新手,我不确定是否可以轻松实现。
【解决方案2】:

我使用正则表达式来解决这个问题。假设 data 是一个包含多个 xml 文档的字符串,并且该句柄是一个函数,它将对每个文档执行一些操作。执行此循环后,数据将为空,或包含不完整的 XML 文档,句柄函数将被调用零次或多次。

while True:
  match = re.match (r'''
        \s*                 # ignore leading whitespace
        (                   # start first group
          <(?P<TAG>\S+).*?> # opening tag (with optional attributes)
            .*?             # stuff in the middle
          </(?P=TAG)>       # closing tag
        )                   # end of first xml document
        (?P<REM>.*)         # anything else
      ''',
    data, re.DOTALL | re.VERBOSE)
  if not match:
    break
  document = match.group (1)
  handle (document)
  data = match.group ('REM')

【讨论】:

  • 根据 OP 的错误消息和随后的评论,他有多个 XML 文档,每个文档都以 XML 声明开头——您的答案忽略了声明。
  • john - 这将处理包装在任何标签中的多个连续文档,包括“xml”。我认为它涵盖了这个问题,不是吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-08
  • 1970-01-01
相关资源
最近更新 更多