【问题标题】:ParseError: not well-formed (invalid token) using cElementTreeParseError: not well-formed (invalid token) using cElementTree
【发布时间】:2012-10-14 07:37:12
【问题描述】:

我从可能包含未经处理的用户贡献内容的外部来源接收到 xml 字符串。

以下 xml 字符串在 cElementTree 中给出了 ParseError:

>>> print repr(s)
'<Comment>dddddddd\x08\x08\x08\x08\x08\x08_____</Comment>'
>>> import xml.etree.cElementTree as ET
>>> ET.XML(s)

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    ET.XML(s)
  File "<string>", line 106, in XML
ParseError: not well-formed (invalid token): line 1, column 17

有没有办法让 cElementTree 不抱怨?

【问题讨论】:

    标签: python parsing elementtree


    【解决方案1】:

    这段代码 sn-p 对我有用。我在解析一批 XML 文件时遇到问题。我不得不将它们编码为“iso-8859-5”

    import xml.etree.ElementTree as ET
    
    tree = ET.parse(filename, parser = ET.XMLParser(encoding = 'iso-8859-5'))
    

    【讨论】:

      【解决方案2】:

      在整个 WWW 中进行了大量搜索后,我才发现如果您希望 XML 解析器正常工作,您必须转义某些字符!以下是我的做法和为我工作的方式:

      escape_illegal_xml_characters = lambda x: re.sub(u'[\x00-\x08\x0b\x0c\x0e-\x1F\uD800-\uDFFF\uFFFE\uFFFF]', '', x)
      

      并像平常一样使用它:

      ET.XML(escape_illegal_xml_characters(my_xml_string)) #instead of ET.XML(my_xml_string)
      

      【讨论】:

        【解决方案3】:

        在我的情况下,lxml 解决了这个问题

        from lxml import etree
        
        for _, elein etree.iterparse(xml_file, tag='tag_i_wanted', unicode='utf-8'):
            print(ele.tag, ele.text)  
        

        在另一种情况下,

        parser = etree.XMLParser(recover=True)
        tree = etree.parse(xml_file, parser=parser)
        tags_needed = tree.iter('TAG NAME')
        

        感谢theeastcoastwest

        Python 2.7

        【讨论】:

          【解决方案4】:

          唯一对我有用的是我必须在打开文件时添加模式和编码,如下所示:

          with open(filenames[0], mode='r',encoding='utf-8') as f:
               readFile()
          

          否则,如果我只是这样做,每次都会失败并出现无效令牌错误:

           f = open(filenames[0], 'r')
           readFile()
          

          【讨论】:

            【解决方案5】:

            我在这里的答案中尝试了其他解决方案,但没有运气。因为我只需要从单个 xml 节点中提取值,所以我放弃并编写了我的函数来这样做:

            def ParseXmlTagContents(source, tag, tagContentsRegex):
                openTagString = "<"+tag+">"
                closeTagString = "</"+tag+">"
                found = re.search(openTagString + tagContentsRegex + closeTagString, source)
                if found:   
                    start = found.regs[0][0]
                    end = found.regs[0][1]
                    return source[start+len(openTagString):end-len(closeTagString)]
                return ""
            

            示例用法如下:

            <?xml version="1.0" encoding="utf-16"?>
            <parentNode>
                <childNode>123</childNode>
            </parentNode>
            
            ParseXmlTagContents(xmlString, "childNode", "[0-9]+")
            

            【讨论】:

              【解决方案6】:

              以上修复均不适合我。唯一有效的是使用BeautifulSoup 而不是ElementTree,如下所示:

              from bs4 import BeautifulSoup
              
              with open("data/myfile.xml") as fp:
                  soup = BeautifulSoup(fp, 'xml')
              

              然后你可以搜索树:

              soup.find_all('mytag')
              

              【讨论】:

              • 没有来自BeautifulSoup 的'xml 解析器'。当您向BeautifulSoup 提供xml 参数时,it uses lxml's XML parser under the hood.
              • @BioGeek 谢谢,是的,我的意思是你需要安装 lxml 才能以这种方式使用 BeautifulSoup。至少在我的情况下,我必须单独安装......
              【解决方案7】:

              这很可能是编码错误。例如,我有一个以 UTF-8-BOM 编码的 xml 文件(从 Notepad++ 编码菜单中检查)并收到类似的错误消息。

              解决方法(Python 3.6)

              import io
              from xml.etree import ElementTree as ET
              
              with io.open(file, 'r', encoding='utf-8-sig') as f:
                  contents = f.read()
                  tree = ET.fromstring(contents)
              

              检查 xml 文件的编码。如果它使用不同的编码,请相应地更改“utf-8-sig”。

              【讨论】:

                【解决方案8】:

                我一直遇到类似的问题。终于弄清楚了在我的特殊情况下的根本原因是什么。如果您从位于同一文件夹中的多个 XML 文件中读取数据,您还将解析 .DS_Store 文件。 在解析之前添加这个条件

                for file in files:
                    if file.endswith('.xml'):
                       run_your_code...
                

                这个技巧也帮助了我

                【讨论】:

                  【解决方案9】:

                  使用 Python 的 ElementTree 为我提供了一个解决方案...这有无效的令牌错误:

                  # -*- coding: utf-8 -*-
                  import xml.etree.ElementTree as ET
                  
                  xml = u"""<?xml version='1.0' encoding='utf8'?>
                  <osm generator="pycrocosm server" version="0.6"><changeset created_at="2017-09-06T19:26:50.302136+00:00" id="273" max_lat="0.0" max_lon="0.0" min_lat="0.0" min_lon="0.0" open="true" uid="345" user="john"><tag k="test" v="Съешь же ещё этих мягких французских булок да выпей чаю" /><tag k="foo" v="bar" /><discussion><comment data="2015-01-01T18:56:48Z" uid="1841" user="metaodi"><text>Did you verify those street names?</text></comment></discussion></changeset></osm>"""
                  
                  xmltest = ET.fromstring(xml.encode("utf-8"))
                  

                  但是,它可以在编码类型中添加连字符:

                  <?xml version='1.0' encoding='utf-8'?>
                  

                  最奇怪的。 Someonepython docs 中发现了这个脚注:

                  XML 输出中包含的编码字符串应符合 适当的标准。例如,“UTF-8”是有效的,但“UTF8”是 不是。

                  【讨论】:

                    【解决方案10】:

                    我遇到了同样的错误(使用 ElementTree)。就我而言,这是因为编码,我能够解决它而无需使用外部库。希望这有助于其他人根据标题找到这个问题。 (reference)

                    import xml.etree.ElementTree as ET
                    parser = ET.XMLParser(encoding="utf-8")
                    tree = ET.fromstring(xmlstring, parser=parser)
                    

                    编辑:基于 cmets,此答案可能已过时。但是,当它被回答时,这确实起作用了......

                    【讨论】:

                    • parse 函数具有parser 属性,因此您可以给它一个文件名作为输入而不是字符串:e = ElementTree.parse(my_file, parser=ElementTree.XMLParser(encoding='iso-8859-5') )
                    • 如第一条评论所述,fromstring 不接受解析器参数。这个答案在语法上是错误的。
                    • 文档建议 ET.fromstringlist([xmlstring], parser=parser) 可用于实现此处的预期目标。
                    【解决方案11】:

                    帮助我解决这个错误的是胡安的回答 - https://stackoverflow.com/a/20204635/4433222 但这还不够——经过努力,我发现一个 XML 文件需要用 UTF-8 保存,而不需要 BOM 编码。

                    该解决方案不适用于“普通”UTF-8。

                    【讨论】:

                    • 你对此有何论证?
                    • 哦,那是很久以前的事了。实际上不记得了,但可能我只是在记事本++中正确保存了一个文件
                    【解决方案12】:

                    它似乎在抱怨\x08,你需要逃避它。

                    编辑:

                    或者你可以让解析器使用recover忽略错误

                    from lxml import etree
                    parser = etree.XMLParser(recover=True)
                    etree.fromstring(xmlstring, parser=parser)
                    

                    【讨论】:

                    • 我不想更改我收到的 XML 内容的任何内容,我只需将其转换为 cElementTree Element
                    • 转义与更改 btw 不同。
                    • recover 它不再适用于 ElementTrees XMLParser,对吧?或者什么是'lxml'?这不是香草蟒?
                    【解决方案13】:

                    参见 this answer 的另一个问题和 XML 规范的 according part

                    退格 U+0008 是 XML 文档中的无效字符。它必须表示为转义实体&amp;#8;,并且不能直接出现。

                    如果您需要处理此 XML sn-p,则必须在将其输入 XML 解析器之前将 \x08 替换为 s

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2021-11-26
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-05-16
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多