【问题标题】:Convert Python ElementTree to string将 Python ElementTree 转换为字符串
【发布时间】:2013-02-24 14:26:16
【问题描述】:

每当我拨打ElementTree.tostring(e) 时,都会收到以下错误消息:

AttributeError: 'Element' object has no attribute 'getroot'

还有其他方法可以将 ElementTree 对象转换为 XML 字符串吗?

追溯:

Traceback (most recent call last):
  File "Development/Python/REObjectSort/REObjectResolver.py", line 145, in <module>
    cm = integrateDataWithCsv(cm, csvm)
  File "Development/Python/REObjectSort/REObjectResolver.py", line 137, in integrateDataWithCsv
    xmlstr = ElementTree.tostring(et.getroot(),encoding='utf8',method='xml')
AttributeError: 'Element' object has no attribute 'getroot'

【问题讨论】:

    标签: python xml marshalling elementtree


    【解决方案1】:

    Element 对象没有.getroot() 方法。挂断电话,.tostring() 电话就可以了:

    xmlstr = ElementTree.tostring(et, encoding='utf8', method='xml')
    

    如果你有ElementTree instance,你只需要使用.getroot()

    其他说明:

    • 这会产生一个 bytestring,在 Python 3 中是 bytes 类型。
      如果你必须有一个str 对象,你有两个选择:

      1. 从 UTF-8 解码得到的字节值:xmlstr.decode("utf8")

      2. 使用encoding='unicode';这避免了编码/解码循环:

        xmlstr = ElementTree.tostring(et, encoding='unicode', method='xml')
        
    • 如果您想要 UTF-8 编码的字节字符串值或使用 Python 2,请考虑到 ElementTree 无法正确地将 utf8 检测为标准 XML 编码,因此它将添加 &lt;?xml version='1.0' encoding='utf8'?&gt; 声明。如果您想防止这种情况,请使用 utf-8UTF-8(带破折号)。使用encoding="unicode"时不添加声明头。

    【讨论】:

      【解决方案2】:

      如何将ElementTree.Element 转换为字符串?

      对于 Python 3:

      xml_str = ElementTree.tostring(xml, encoding='unicode')
      

      对于 Python 2:

      xml_str = ElementTree.tostring(xml, encoding='utf-8')
      

      以下内容同时兼容 Python 2 和 3,但 only works for Latin characters:

      xml_str = ElementTree.tostring(xml).decode()
      

      示例用法

      from xml.etree import ElementTree
      
      xml = ElementTree.Element("Person", Name="John")
      xml_str = ElementTree.tostring(xml).decode()
      print(xml_str)
      

      输出:

      <Person Name="John" />
      

      说明

      尽管顾名思义,ElementTree.tostring() 在 Python 2 和 3 中默认返回一个字节串。这是 Python 3 中的一个问题,uses Unicode for strings

      在 Python 2 中,您可以将 str 类型用于文本和二进制数据。 不幸的是,这两种不同概念的融合可能导致 有时适用于任何一种数据的脆弱代码,有时 不是。 [...]

      为了使文本和二进制数据之间的区别更加清晰和明显,[Python 3] 使文本和二进制数据成为不能盲目混合在一起的不同类型

      来源:Porting Python 2 Code to Python 3

      如果我们知道正在使用的 Python 版本,我们可以将编码指定为unicodeutf-8。否则,如果我们需要同时兼容 Python 2 和 3,我们可以使用decode() 转换为正确的类型。

      作为参考,我将.tostring() 在 Python 2 和 Python 3 之间的结果进行了比较。

      ElementTree.tostring(xml)
      # Python 3: b'<Person Name="John" />'
      # Python 2: <Person Name="John" />
      
      ElementTree.tostring(xml, encoding='unicode')
      # Python 3: <Person Name="John" />
      # Python 2: LookupError: unknown encoding: unicode
      
      ElementTree.tostring(xml, encoding='utf-8')
      # Python 3: b'<Person Name="John" />'
      # Python 2: <Person Name="John" />
      
      ElementTree.tostring(xml).decode()
      # Python 3: <Person Name="John" />
      # Python 2: <Person Name="John" />
      

      感谢Martijn Peters 指出str 数据类型在Python 2 和3 之间发生了变化。


      为什么不使用 str()?

      在大多数情况下,使用str() 将是“cannonical”将对象转换为字符串的方式。不幸的是,将它与Element 一起使用会以十六进制字符串的形式返回对象在内存中的位置,而不是对象数据的字符串表示形式。

      from xml.etree import ElementTree
      
      xml = ElementTree.Element("Person", Name="John")
      print(str(xml))  # <Element 'Person' at 0x00497A80>
      

      【讨论】:

      • 在 Python 2 中 ElementTree.tostring() 也会生成一个字节串。 str 类型 在 Python 2 中是一个字节串(Python 3 的 str 类型在 Python 2 中称为 unicode)。
      • 该功能仅添加到 Python 3 版本,并没有向后移植到 Python 2。如果是,您将得到一个 unicode 字符串。
      【解决方案3】:

      非拉丁回答扩展

      扩展至@Stevoisiak's answer 并处理非拉丁字符。只有一种方式会向您显示非拉丁字符。在 Python 3 和 Python 2 上,一种方法是不同的。

      输入

      xml = ElementTree.fromstring('<Person Name="크리스" />')
      xml = ElementTree.Element("Person", Name="크리스")  # Read Note about Python 2
      

      注意:在 Python 2 中,当调用 toString(...) 代码时,将 xmlElementTree.Element("Person", Name="크리스") 分配将引发错误...

      UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 0: ordinal not in range(128)

      输出

      ElementTree.tostring(xml)
      # Python 3 (크리스): b'<Person Name="&#53356;&#47532;&#49828;" />'
      # Python 3 (John): b'<Person Name="John" />'
      
      # Python 2 (크리스): <Person Name="&#53356;&#47532;&#49828;" />
      # Python 2 (John): <Person Name="John" />
      
      
      ElementTree.tostring(xml, encoding='unicode')
      # Python 3 (크리스): <Person Name="크리스" />             <-------- Python 3
      # Python 3 (John): <Person Name="John" />
      
      # Python 2 (크리스): LookupError: unknown encoding: unicode
      # Python 2 (John): LookupError: unknown encoding: unicode
      
      ElementTree.tostring(xml, encoding='utf-8')
      # Python 3 (크리스): b'<Person Name="\xed\x81\xac\xeb\xa6\xac\xec\x8a\xa4" />'
      # Python 3 (John): b'<Person Name="John" />'
      
      # Python 2 (크리스): <Person Name="크리스" />             <-------- Python 2
      # Python 2 (John): <Person Name="John" />
      
      ElementTree.tostring(xml).decode()
      # Python 3 (크리스): <Person Name="&#53356;&#47532;&#49828;" />
      # Python 3 (John): <Person Name="John" />
      
      # Python 2 (크리스): <Person Name="&#53356;&#47532;&#49828;" />
      # Python 2 (John): <Person Name="John" />
      
      

      【讨论】:

      • 很好地呼吁非拉丁字符。我已经更新了我的帖子来提及这一点。
      【解决方案4】:

      如果您只是需要它来调试以查看 XML 的外观,那么您可以使用 dump 代替 print(xml.etree.ElementTree.tostring(e)),如下所示:

      xml.etree.ElementTree.dump(e)
      

      这适用于ElementElementTree 对象作为e,所以应该不需要getroot

      documentation of dump 说:

      xml.etree.ElementTree.dump(elem)

      将元素树或元素结构写入sys.stdout。该函数仅用于调试。

      确切的输出格式取决于实现。在这个版本中,它被写成一个普通的 XML 文件。

      elem 是元素树或单个元素。

      3.8 版更改dump() 函数现在保留用户指定的属性顺序。

      【讨论】:

        【解决方案5】:

        我在 Python 3.8 中遇到了同样的问题,之前的答案都没有解决它。问题是 ElementTree 既是模块的名称,也是其中的类的名称。使用别名就清楚了:

        from xml.etree.ElementTree import ElementTree
        import xml.etree.ElementTree as XET
        ...
        ElementTree.tostring(...)  # Attribute-error
        XET.tostring(...)          # Works
        

        【讨论】:

          猜你喜欢
          • 2016-02-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-19
          • 2013-03-13
          • 2017-03-23
          • 2015-03-29
          • 1970-01-01
          相关资源
          最近更新 更多