【问题标题】:Adding new XML node and Pretty printing XML in python在 python 中添加新的 XML 节点和漂亮的打印 XML
【发布时间】:2013-01-09 05:14:03
【问题描述】:

我可以使用 ElementTree 添加 XML 节点,但是当我以文本格式打开 xml 文件时,这会在一行中返回输出,而不是树结构。我也尝试使用 minidom.toprettyxml 但我不知道如何将输出添加到原始 XML。由于我希望脚本在其他环境中可重现,因此我不喜欢使用 lxml 等外部库。有人可以帮助我如何漂亮地打印输出吗? - 蟒蛇2.7

示例 XML。这就是它在文本格式和资源管理器中的外观。

<?xml version="1.0" encoding="utf-8"?>
<default_locators >
  <locator_ref>
    <name>cherry</name>
    <display_name>cherrycherry</display_name>
    <workspace_properties>
      <factory_progid>Workspace</factory_progid>
      <path>InstallDir</path>
    </workspace_properties>
  </locator_ref>
</default_locators>

文本格式和资源管理器的预期输出。

<?xml version="1.0" encoding="utf-8"?>
<default_locators >
  <locator_ref>
    <name>cherry</name>
    <display_name>cherrycherry</display_name>
    <workspace_properties>
      <factory_progid>Workspace</factory_progid>
      <path>InstallDir</path>
    </workspace_properties>
  </locator_ref>
  <locator_ref>
    <name>berry</name>
    <display_name>berryberry</display_name>
    <workspace_properties>
      <factory_progid>Workspace</factory_progid>
      <path>C:\temp\temp</path>
    </workspace_properties>
  </locator_ref>
</default_locators>

我的脚本

#coding: cp932

import xml.etree.ElementTree as ET

tree = ET.parse(r"C:\DefaultLocators.xml")
root = tree.getroot()

locator_ref = ET.SubElement(root, "locator_ref")
name = ET.SubElement(locator_ref, "name")
name.text = " berry"
display_name = ET.SubElement(locator_ref, "display_name")
display_name.text = "berryberry"
workspace_properties = ET.SubElement(locator_ref, "workspace_properties")
factory_progid = ET.SubElement(workspace_properties,"factory_progid")
factory_progid.text = "Workspace"
path = ET.SubElement(workspace_properties, "path")
path.text = r"c:\temp\temp"

tree.write(r"C:\DefaultLocators.xml", encoding='utf-8')

返回的输出。运行我的脚本后,新节点被添加到我的 sample.xml 文件中,但它在一行中返回输出,所有换行符和缩进都从原始 sample.xml 文件中删除。至少当我以文本格式打开 sample.xml 文件时它是这样的。但是,当我在资源管理器中打开 sample.xml 文件时,它看起来很好。我仍然像以前一样看到换行符和缩进。即使在运行脚本后,如何将原始树结构保持为文本格式?

<default_locators>
  <locator_ref>
    <name>cherry</name>
    <display_name>cherrycherry</display_name>
    <workspace_properties>
      <factory_progid>Workspace</factory_progid>
      <path>InstallDir</path>
    </workspace_properties>
  </locator_ref>
<locator_ref><name> berry</name><display_name>berryberry</display_name><workspace_properties><factory_progid>Workspace</factory_progid><path>c:\temp\temp</path></workspace_properties></locator_ref></default_locators>

【问题讨论】:

    标签: python xml elementtree


    【解决方案1】:

    在处理元素时,你可以这样做:element.tail = '\n' 然后,它将被写成一行。

    【讨论】:

      【解决方案2】:

      在 elementTree 中写你的 xml 为:

      import xml.etree.ElementTree as ET
      
      
      def serialize_xml(write, elem, encoding, qnames, namespaces):
          tag = elem.tag
          text = elem.text
          if tag is ET.Comment:
              write("<!--%s-->" % _encode(text, encoding))
          elif tag is ET.ProcessingInstruction:
              write("<?%s?>" % _encode(text, encoding))
          else:
              tag = qnames[tag]
              if tag is None:
                  if text:
                      write(_escape_cdata(text, encoding))
                  for e in elem:
                      serialize_xml(write, e, encoding, qnames, None)
              else:
                  write("\n<" + tag) ## '\n' added by namit
                  items = elem.items()
                  if items or namespaces:
                      if namespaces:
                          for v, k in sorted(namespaces.items(),
                                             key=lambda x: x[1]):  # sort on prefix
                              if k:
                                  k = ":" + k
                              write(" xmlns%s=\"%s\"" % (
                                  k.encode(encoding),
                                  _escape_attrib(v, encoding)
                                  ))
                      for k, v in sorted(items):  # lexical order
                          if isinstance(k, QName):
                              k = k.text
                          if isinstance(v, QName):
                              v = qnames[v.text]
                          else:
                              v = _escape_attrib(v, encoding)
                          write(" %s=\"%s\"" % (qnames[k], v))
                  if text or len(elem):
                      write(">")
                      if text:
                          write(ET._escape_cdata(text, encoding))
                      for e in elem:
                          serialize_xml(write, e, encoding, qnames, None)
                      write("</" + tag + ">")
                  else:
                      write(" />")
          if elem.tail:
              write(ET._escape_cdata(elem.tail, encoding))
      
      ET._serialize_xml=serialize_xml
      
      tree = ET.parse(r"samplexml.xml")
      root = tree.getroot()
      
      locator_ref = ET.SubElement(root, "locator_ref")
      name = ET.SubElement(locator_ref, "name")
      name.text = " berry"
      display_name = ET.SubElement(locator_ref, "display_name")
      display_name.text = "berryberry"
      workspace_properties = ET.SubElement(locator_ref, "workspace_properties")
      factory_progid = ET.SubElement(workspace_properties,"factory_progid")
      factory_progid.text = "WorkspaceFactory"
      path = ET.SubElement(workspace_properties, "path")
      
      ins_out=open("samplexml_1.xml",'wb',1000)
      ET.ElementTree(locator_ref).write(ins_out,encoding="ASCII")
      ins_out.close()
      

      这将在单行中写入完整的文件;无需在 xml 尾部添加空格。

      【讨论】:

      • @user1027101:检查更新的帖子;我已经为此编写了完整的代码。
      • 感谢您的代码。我试过了,它就像你提到的那样工作,但你知道我如何将输出插入或附加到现有的 XML 文件而不是覆盖它吗?
      • @user1027101:不;我们不能;那是像任何其他文件一样的文件;它不是我们可以插入或附加的任何 python 对象;我们必须创建新的或覆盖现有的。
      • 虽然上面的脚本不完整,但我可以将一些节点添加到现有的 XML 文件中。请参阅上面的“以 txt 格式返回的输出”。我想要的只是将输出放在具有适当缩进的树中......
      • @J.F.塞巴斯蒂安:你能帮忙吗?
      【解决方案3】:

      我认为您必须尝试lxml library。这是在 Python 中解析 XML 的最佳方式。 对于这些事情,它有神奇的参数 *pretty_print*。 这是一个例子:

      import lxml.etree as etree
      
      root = etree.Element("root")
      for rn in range(10):
          etree.SubElement(root, "column_%s" % str(rn)).text = str(rn*rn)
      pretty_data = etree.tostring(root, pretty_print=True, encoding = 'utf-8')
      print final_data
      

      结果:http://pastebin.com/y0rkQ78G

      【讨论】:

        猜你喜欢
        • 2012-03-25
        • 2017-12-19
        • 1970-01-01
        • 1970-01-01
        • 2018-10-04
        • 2018-05-27
        相关资源
        最近更新 更多