【问题标题】:xml.parsers.expat.ExpatError: not well-formed (invalid token)xml.parsers.expat.ExpatError:格式不正确(无效令牌)
【发布时间】:2018-02-16 07:10:24
【问题描述】:

当我使用 xmltodict 加载下面的 xml 文件时,出现错误: xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 1

这是我的文件:

<?xml version="1.0" encoding="utf-8"?>
<mydocument has="an attribute">
  <and>
    <many>elements</many>
    <many>more elements</many>
  </and>
  <plus a="complex">
    element as well
  </plus>
</mydocument>

来源:

import xmltodict
with open('fileTEST.xml') as fd:
   xmltodict.parse(fd.read())

我在 Windows 10 上,使用 Python 3.6 和 xmltodict 0.11.0

如果我使用 ElementTree 它可以工作

tree = ET.ElementTree(file='fileTEST.xml')
    for elem in tree.iter():
            print(elem.tag, elem.attrib)

mydocument {'has': 'an attribute'}
and {}
many {}
many {}
plus {'a': 'complex'}

注意:我可能遇到了换行问题。
注意 2:我在两个不同的文件上使用了 Beyond Compare。
它在 UTF-8 BOM 编码的文件上崩溃,并在 UTF-8 文件上工作。
UTF-8 BOM 是一个字节序列 (EF BB BF),允许阅读器将文件识别为以 UTF-8 编码。

【问题讨论】:

  • 您得到的确切回溯是什么?我刚刚尝试按照您展示的方式进行操作,它对我来说可以正常工作,使用字节或 unicode(Python 3 字符串)作为输入。
  • 错误是:xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 1

标签: python-3.x windows-10


【解决方案1】:

我想你忘了定义编码类型。 我建议您尝试将该 xml 文件初始化为字符串变量:

import xml.etree.ElementTree as ET
import xmltodict
import json


tree = ET.parse('your_data.xml')
xml_data = tree.getroot()
#here you can change the encoding type to be able to set it to the one you need
xmlstr = ET.tostring(xml_data, encoding='utf-8', method='xml')

data_dict = dict(xmltodict.parse(xmlstr))

【讨论】:

  • 奇怪的是,这对我有用,而无需更改默认编码类型,在 ET 和 xmltodict 上都设置为 'utf-8'
【解决方案2】:

就我而言,问题在于前 3 个字符。所以删除它们是有效的:

import xmltodict
from xml.parsers.expat import ExpatError

with open('your_data.xml') as f:
    data = f.read()
    try:
        doc = xmltodict.parse(data)
    except ExpatError:
        doc = xmltodict.parse(data[3:])

【讨论】:

    【解决方案3】:

    Python 3

    一个班轮

    data: dict = xmltodict.parse(ElementTree.tostring(ElementTree.parse(path).getroot()))
    

    .json 和 .xml 的助手

    我写了一个小辅助函数来从给定的path 加载.json 和.xml 文件。 我认为它对这里的某些人可能会派上用场:

    import json
    import xml.etree.ElementTree
    
    def load_json(path: str) -> dict:  
        if path.endswith(".json"):
            print(f"> Loading JSON from '{path}'")
            with open(path, mode="r") as open_file:
                content = open_file.read()
    
            return json.loads(content)
        elif path.endswith(".xml"):
            print(f"> Loading XML as JSON from '{path}'")
            xml = ElementTree.tostring(ElementTree.parse(path).getroot())
            return xmltodict.parse(xml, attr_prefix="@", cdata_key="#text", dict_constructor=dict)
    
        print(f"> Loading failed for '{path}'")
        return {}
    

    备注

    • 如果您想去掉 json 输出中的 @ 和 #text 标记,请使用参数 attr_prefix="" 和 cdata_key=""

    • 通常xmltodict.parse() 返回OrderedDict,但您可以使用参数dict_constructor=dict 更改它

    用法

    path = "my_data.xml"
    data = load_json(path)
    print(json.dumps(data, indent=2))
    
    # OUTPUT
    #
    # > Loading XML as JSON from 'my_data.xml' 
    # {
    #   "mydocument": {
    #     "@has": "an attribute",
    #     "and": {
    #       "many": [
    #         "elements",
    #         "more elements"
    #       ]
    #     },
    #     "plus": {
    #       "@a": "complex",
    #       "#text": "element as well"
    #     }
    #   }
    # }
    

    来源

    【讨论】:

      【解决方案4】:

      在我的情况下,文件是使用字节顺序标记保存的,这是 notepad++ 的默认设置

      我将没有BOM的文件重新保存为纯utf8。

      【讨论】:

        【解决方案5】:

        xmltodict 似乎无法解析&lt;?xml version="1.0" encoding="utf-8"?&gt;

        如果您删除此行,它会起作用。

        【讨论】:

        • 显然它可以在没有 xml 声明的情况下工作;它失败了吗?对我来说,它没有失败。
        • 对我来说,xml 声明失败了,但不是没有它。你知道,我在发布之前尝试了一些事情
        • 我不是想遮遮掩掩。我得到了不同的结果,我不清楚你是否尝试过声明。你用的是什么版本?我正在使用 Python 3.5.2,Expat 2.1.1
        • Python:3.6.3,xmltodict:0.11.0。
        【解决方案6】:

        不特定于原始帖子,但对于那些在不同行也遇到相同错误的人,我能够通过更正 XML/XHTML 错误来修复它。

        在我的例子中,我正在使用的文档有一个带有百分比符号“&”而不是“&”的文本描述,因此为了解决我的问题,我必须先编辑文件,然后再运行解析器。

        【讨论】:

          猜你喜欢
          • 2016-05-04
          • 2018-12-05
          • 2018-09-25
          • 2019-01-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-27
          • 1970-01-01
          相关资源
          最近更新 更多