为什么在python中解析xml文件会在文件中存在“ />”的地方增加空间?

时间:2019-05-02 20:02:58

标签: python xml

当我解析一个xml文件,然后将结果写入输出文件时,原始文件中任何有“ />”的地方都会添加一个空格。有什么办法可以防止它被创建?

我已经编写了一些python代码来更新xml文件中的几个字段,并认为我可以正常工作,但是在原始文件和更新文件之间的sdiff上运行后,我注意到不仅限于所需的行更新。 xml文件中任何有“ />”的地方都以“ />”为前缀。我注释掉了我的所有代码,除了parse命令然后是write命令,并且能够验证它似乎是parse或write命令引起了问题。

选择源XML文件的内容:更新的XML文件:

<QcfName/>                              <QcfName />
<Icf/>                                  <Icf />
<Bidirectional/>                        <Bidirectional />

代码(注释所有其他代码):

tree = ET.parse(inFile)

tree.write(outFile)

我不需要将任何带有“ />”的条目更新为包含空格“ />”。

1 个答案:

答案 0 :(得分:0)

我认为唯一的方法是重新定义ET._serialize_xml并删除以下位置的硬编码空间:

write(" />")

基本上只是从ElementTree复制整个函数,删除空间,并用ET更新任何函数/方法/类引用(例如Comment变成ET.Comment_escape_cdata(text)变成ET._escape_cdata(text),依此类推)

这还不是很漂亮,还需要维护一些其他内容。

示例...

XML输入(input.xml)

<doc>
    <QcfName/>
    <Icf/>
    <Bidirectional/>
</doc>

Python

import xml.etree.ElementTree as ET


def local_serialize_xml(write, elem, qnames, namespaces,
                        short_empty_elements, **kwargs):
    tag = elem.tag
    text = elem.text
    if tag is ET.Comment:
        write("<!--%s-->" % text)
    elif tag is ET.ProcessingInstruction:
        write("<?%s?>" % text)
    else:
        tag = qnames[tag]
        if tag is None:
            if text:
                write(ET._escape_cdata(text))
            for e in elem:
                local_serialize_xml(write, e, qnames, None,
                                    short_empty_elements=short_empty_elements)
        else:
            write("<" + tag)
            items = list(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,
                            ET._escape_attrib(v)
                            ))
                for k, v in sorted(items):  # lexical order
                    if isinstance(k, ET.QName):
                        k = k.text
                    if isinstance(v, ET.QName):
                        v = qnames[v.text]
                    else:
                        v = ET._escape_attrib(v)
                    write(" %s=\"%s\"" % (qnames[k], v))
            if text or len(elem) or not short_empty_elements:
                write(">")
                if text:
                    write(ET._escape_cdata(text))
                for e in elem:
                    local_serialize_xml(write, e, qnames, None,
                                        short_empty_elements=short_empty_elements)
                write("</" + tag + ">")
            else:
                # CHANGED " />" TO "/>"
                write("/>")
    if elem.tail:
        write(ET._escape_cdata(elem.tail))


ET._serialize_xml = local_serialize_xml


tree = ET.parse("input.xml")

tree.write("output.xml")

XML输出(output.xml)

<doc>
    <QcfName/>
    <Icf/>
    <Bidirectional/>
</doc>