【问题标题】:Writing XML to file using LXML使用 LXML 将 XML 写入文件
【发布时间】:2018-02-12 20:58:38
【问题描述】:

我正在尝试使用 LXML 创建一个 XML 文件。到目前为止,我...

from lxml import etree

def exportAsXML(self, filename):
    fields = [
        ('Realm', self.Realm),
        ('ActiveState', self.ActiveState),
        ('Name', self.Name),
        ('Type', self.Type),
        ('Level', self.Level),
        ('Quality', self.Quality),
        ('Bonus', self.Bonus),
        ('AFDPS', self.AFDPS),
        ('Speed', self.Speed),
        ('Origin', self.Origin),
        ('DamageType', self.DamageType),
        ('LeftHand', self.LeftHand),
        ('Requirement', self.Requirement),
        ('Notes', self.Notes,)
    ]

    root = etree.Element('Item')
    for key, value in fields:
        if value != '':
            etree.SubElement(root, key).text = value

    document = open(filename, 'w')
    document.write(etree.tostring(root, pretty_print = True))
    document.close()

这导致TypeError: must be str, not bytes,但我不明白发生了什么。我假设使用 etree.tostring 将 etree 对象转换为字符串,但似乎并非如此。有什么想法吗?

** 更新 **

我要做的是创建一个有效的 XML 文件,该文件使用 LXML 进行整齐格式化并包含一个 DTD(尚未实现)。我已经在我的应用程序的其他领域使用了 LXML,所以我想我会继续使用它。我正在使用 Python 3。

** 更新 2 **

控制台

b'<Item><Realm>All</Realm><ActiveState>Dropped</ActiveState><Name>Band</Name><Type>Wrist</Type><Level>50</Level><Quality>100</Quality><Bonus>35</Bonus><Origin>Quest</Origin></Item>'

文件

<Item><Realm>All</Realm><ActiveState>Dropped</ActiveState><Name>Band</Name><Type>Wrist</Type><Level>50</Level><Quality>100</Quality><Bonus>35</Bonus><Origin>Quest</Origin></Item>

【问题讨论】:

  • 试试etree.SubElement(root, key.decode('utf-8')).text = str(value, 'utf-8')
  • @sKwa 抛出一个新异常:TypeError: decoding str is not supported
  • 所以尝试将str(value, 'utf-8')修改为str(value)
  • @sKwa 试过了,没有骰子。和以前一样的例外。不知道我在这里缺少什么。我已经梳理了文档,并查看了其他示例,但仍然无法弄清楚。
  • 上线失败-etree.tostring(...)?

标签: python xml python-3.x lxml


【解决方案1】:

对于 XML 文件,只需使用 open() 中的 'wb' 参数并考虑上下文管理器 with

with open(filename, 'wb') as doc:
   doc.write(etree.tostring(root, pretty_print = True))

作为演示,下面测试 OP 的例程,对 self 变量稍作更改,并以漂亮的打印格式输出:

def exportAsXML(filename):
    fields = [
        ('Realm', 'self.Realm'),
        ('ActiveState', 'self.ActiveState'),
        ('Name', 'self.Name'),
        ('Type', 'self.Type'),
        ('Level', 'self.Level'),
        ('Quality', 'self.Quality'),
        ('Bonus', 'self.Bonus'),
        ('AFDPS', 'self.AFDPS'),
        ('Speed', 'self.Speed'),
        ('Origin', 'self.Origin'),
        ('DamageType', 'self.DamageType'),
        ('LeftHand', 'self.LeftHand'),
        ('Requirement', 'self.Requirement'),
        ('Notes', 'self.Notes')
    ]

    root = etree.Element('Item')
    for key, value in fields:
        if value != '':
            etree.SubElement(root, key).text = value

    with open(filename, 'wb') as doc:
        doc.write(etree.tostring(root, pretty_print = True))

exportAsXML('Output.xml')

输出

<Item>
  <Realm>self.Realm</Realm>
  <ActiveState>self.ActiveState</ActiveState>
  <Name>self.Name</Name>
  <Type>self.Type</Type>
  <Level>self.Level</Level>
  <Quality>self.Quality</Quality>
  <Bonus>self.Bonus</Bonus>
  <AFDPS>self.AFDPS</AFDPS>
  <Speed>self.Speed</Speed>
  <Origin>self.Origin</Origin>
  <DamageType>self.DamageType</DamageType>
  <LeftHand>self.LeftHand</LeftHand>
  <Requirement>self.Requirement</Requirement>
  <Notes>self.Notes</Notes>
</Item>

【讨论】:

  • 这行得通,但它在 1 行上打印所有内容。我假设pretty_print = True 会纠正这个问题。
  • 如果etree 指向lxml.etree,则应该如此。您的帖子没有指明图书馆,也没有设置可重复的示例供我们验证。尝试在控制台print(etree.tostring(..., pretty_print = True)) 中打印。
  • 啊!另一个问题是您的 XML 输出没有 root。请发布 etree 字符串。
  • 请原谅我的困惑,我是在 Python 中使用 xml 的新手,您在寻找什么字符串?我在原始帖子中添加了from lxml import etree 以进行澄清。 print(...) 产生一个单行字符串 b'&lt;Item&gt;\n ... &lt;/item&gt;
  • 是的,我可以在 Windows 7 机器上确认。很高兴我们发现了问题!写字板和浏览器会显示缩进。记事本需要unicode 编码以尊重换行符和制表符,您可以传入etree.tostring(root, encoding='unicode', pretty_print = True) 并将open() 参数从wb 更改为w,因为这将转换为字节到字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多