【问题标题】:How to write an XML file without header in Python?如何在 Python 中编写没有标头的 XML 文件?
【发布时间】:2010-05-29 00:28:41
【问题描述】:

当使用 Python 的常用 XML 工具(例如 xml.dom.minidom)进行 XML 写入时,文件的开头总是像

<?xml version="1.0"?>

[...]

虽然这是完全合法的 XML 代码,甚至建议使用标头,但我想摆脱它,因为我正在使用的程序之一在这里有问题。

我似乎在xml.dom.minidom 中找不到合适的选项,所以我想知道是否还有其他包允许忽略标题。

干杯,

尼哥

【问题讨论】:

标签: python xml


【解决方案1】:

标题在Document 中打印。如果直接打印节点,是不会打印header的。

root = doc.childNodes[0]
root.toprettyxml(encoding="utf-8")

【讨论】:

    【解决方案2】:

    很遗憾,minidom 不允许您选择忽略 XML 声明。

    但您始终可以通过在文档的根元素上调用 toxml() 而不是 document 来自行序列化文档内容。那么你将不会得到 XML 声明:

    xml= document.documentElement.toxml('utf-8')
    

    ...但是您也不会得到根元素之外的任何其他内容,例如 DOCTYPE,或任何 cmets 或处理指令。如果您需要它们,请一个接一个地序列化文档对象的每个子对象:

    xml= '\n'.join(node.toxml('utf-8') for node in document.childNodes)
    

    我想知道是否还有其他允许忽略标题的包。

    DOM Level 3 LS defines 一个 xml-declaration 配置参数,您可以使用它来抑制它。我所知道的唯一 Python 实现是 pxdom,它在标准支持方面非常全面,但一点也不快。

    【讨论】:

    • 作为记录,LXML 和 Python 2.7 ElementTree API 接受 xml_declaration=False on .write() 并且 LXML 和 cElementTree 都非常快。
    • 2018年的一些新闻到“没有xml-declaration”? XML 似乎被 Python 抛弃了……改用 Java? PS:none here.
    【解决方案3】:

    只需将第一行替换为空白即可:

    import xml.dom.minidom as MD     
    <XML String>.replace(MD.Document().toxml()+'\n', '') 
    

    【讨论】:

      【解决方案4】:

      如果你想使用 minidom 并保持“漂亮”,作为一个快速/hacky 修复如何:

      xml_without_declaration.py

      import xml.dom.minidom as xml
      
      doc = xml.Document()
      
      declaration = doc.toxml()
      
      a = doc.createElement("A")
      doc.appendChild(a)
      b = doc.createElement("B")
      a.appendChild(b)
      
      xml = doc.toprettyxml()[len(declaration):]
      
      print xml
      

      【讨论】:

      • 这会在字符串的开头留下一个新行。用xml = doc.toprettyxml()[(len(declaration) + 1):]修复。
      【解决方案5】:

      如果您打算使用 minidom,只需扫描回文件并在写入所需的所有 XML 后删除第一行。

      【讨论】:

        【解决方案6】:

        您也许可以使用删除第一个标签的自定义类文件对象,例如:

        class RemoveFirstLine:
            def __init__(self, f):
                self.f = f
                self.xmlTagFound = False
        
            def __getattr__(self, attr):
                return getattr(self, self.f)
        
            def write(self, s):
                if not self.xmlTagFound:
                    x = 0 # just to be safe
                    for x, c in enumerate(s):
                        if c == '>':
                            self.xmlTagFound = True
                            break
                    self.f.write(s[x+1:])
                else:
                    self.f.write(s)
        
        ...
        f = RemoveFirstLine(open('path', 'wb'))
        Node.writexml(f, encoding='UTF-8')
        

        或类似的东西。这样做的好处是,如果 XML 文件相当大,则不必完全重写文件。

        【讨论】:

          【解决方案7】:

          纯粹主义者可能不喜欢听这个,但我发现使用 XML 解析器来生成 XML 有点矫枉过正。只需将其直接生成为字符串即可。这也使您可以生成比您可以保存在内存中的文件更大的文件,而这是 DOM 无法做到的。阅读 XML 是另一回事。

          【讨论】:

          • 这充满了陷阱。序列化 XML 比解析它更容易,但它仍然需要相当小心才能正确处理。属性值中的空格转义(以避免解析时的规范化)、]]&gt; 问题、拆分 CDATA 部分(特别是如果您需要非 UTF-8 输出)以及最重要的是序列化命名空间 DOM 的复杂性。您犯错误并生成格式不正确的 XML。然后所有卑鄙的孩子都会笑。
          【解决方案8】:

          使用字符串替换

          from xml.dom import minidom
          mydoc = minidom.parse('filename.xml')
          
          
          with open(newfile, "w" ) as fs:
              fs.write(mydoc.toxml().replace('?xml version="1.0" ?>', ''))
              fs.close()
          

          就是这样;)

          【讨论】:

            猜你喜欢
            • 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
            相关资源
            最近更新 更多