Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does parse of xml file in python add space where there is "/>" in the file?

Tags:

python

xml

When I parse an xml file and then write the result to an output file a space is added wherever there is an "/>" in the original file. Is there a way I can keep this from being created?

I've written some python code to update a couple of fields in an xml file and thought I had everything working but after running on sdiff between the original file and the updated file I noticed that more than just the desired lines were being updated. Anywhere there was "/>" in the xml file it had a space prefixed to it " />". I commented out all of my code except for the parse command and then the write command and was able to verify that it appears the parse or write command is causing the problem.

Select contents of Source XML file: Updated XML file:

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

Code (commented out all other code):

tree = ET.parse(inFile)

tree.write(outFile)

I need to not have any entries with "/>" get updated to include a space " />"

like image 745
bschro Avatar asked Feb 01 '26 13:02

bschro


1 Answers

I think the only way to do this is to redefine ET._serialize_xml and remove the hardcoded space in:

write(" />")

Basically just copy the entire function from ElementTree, remove the space, and update any function/method/class references with ET (like Comment becomes ET.Comment, _escape_cdata(text) becomes ET._escape_cdata(text), etc.)

It's not pretty though and something additional you'd have to maintain.

Example...

XML Input (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 (output.xml)

<doc>
    <QcfName/>
    <Icf/>
    <Bidirectional/>
</doc>
like image 176
Daniel Haley Avatar answered Feb 04 '26 03:02

Daniel Haley



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!