How to write XML declaration using xml.etree.ElementTree

后端 未结 11 941
长情又很酷
长情又很酷 2020-11-30 05:11

I am generating an XML document in Python using an ElementTree, but the tostring function doesn\'t include an XML declaration when converting to plaintext.

相关标签:
11条回答
  • 2020-11-30 05:42

    I encounter this issue recently, after some digging of the code, I found the following code snippet is definition of function ElementTree.write

    def write(self, file, encoding="us-ascii"):
        assert self._root is not None
        if not hasattr(file, "write"):
            file = open(file, "wb")
        if not encoding:
            encoding = "us-ascii"
        elif encoding != "utf-8" and encoding != "us-ascii":
            file.write("<?xml version='1.0' encoding='%s'?>\n" % 
         encoding)
        self._write(file, self._root, encoding, {})
    

    So the answer is, if you need write the XML header to your file, set the encoding argument other than utf-8 or us-ascii, e.g. UTF-8

    0 讨论(0)
  • 2020-11-30 05:43

    If you include the encoding='utf8', you will get an XML header:

    xml.etree.ElementTree.tostring writes a XML encoding declaration with encoding='utf8'

    Sample Python code (works with Python 2 and 3):

    import xml.etree.ElementTree as ElementTree
    
    tree = ElementTree.ElementTree(
        ElementTree.fromstring('<xml><test>123</test></xml>')
    )
    root = tree.getroot()
    
    print('without:')
    print(ElementTree.tostring(root, method='xml'))
    print('')
    print('with:')
    print(ElementTree.tostring(root, encoding='utf8', method='xml'))
    

    Python 2 output:

    $ python2 example.py
    without:
    <xml><test>123</test></xml>
    
    with:
    <?xml version='1.0' encoding='utf8'?>
    <xml><test>123</test></xml>
    

    With Python 3 you will note the b prefix indicating byte literals are returned (just like with Python 2):

    $ python3 example.py
    without:
    b'<xml><test>123</test></xml>'
    
    with:
    b"<?xml version='1.0' encoding='utf8'?>\n<xml><test>123</test></xml>"
    
    0 讨论(0)
  • 2020-11-30 05:46

    The minimal working example with ElementTree package usage:

    import xml.etree.ElementTree as ET
    
    document = ET.Element('outer')
    node = ET.SubElement(document, 'inner')
    node.text = '1'
    res = ET.tostring(document, encoding='utf8', method='xml').decode()
    print(res)
    

    the output is:

    <?xml version='1.0' encoding='utf8'?>
    <outer><inner>1</inner></outer>
    
    0 讨论(0)
  • 2020-11-30 05:49

    Including 'standalone' in the declaration

    I didn't found any alternative for adding the standalone argument in the documentation so I adapted the ET.tosting function to take it as an argument.

    from xml.etree import ElementTree as ET
    
    # Sample
    document = ET.Element('outer')
    node = ET.SubElement(document, 'inner')
    et = ET.ElementTree(document)
    
     # Function that you need   
     def tostring(element, declaration, encoding=None, method=None,):
         class dummy:
             pass
         data = []
         data.append(declaration+"\n")
         file = dummy()
         file.write = data.append
         ET.ElementTree(element).write(file, encoding, method=method)
         return "".join(data)
    # Working example
    xdec = """<?xml version="1.0" encoding="UTF-8" standalone="no" ?>"""    
    xml = tostring(document, encoding='utf-8', declaration=xdec)
    
    0 讨论(0)
  • 2020-11-30 05:58

    I would use ET:

    try:
        from lxml import etree
        print("running with lxml.etree")
    except ImportError:
        try:
            # Python 2.5
            import xml.etree.cElementTree as etree
            print("running with cElementTree on Python 2.5+")
        except ImportError:
            try:
                # Python 2.5
                import xml.etree.ElementTree as etree
                print("running with ElementTree on Python 2.5+")
            except ImportError:
                try:
                    # normal cElementTree install
                    import cElementTree as etree
                    print("running with cElementTree")
                except ImportError:
                   try:
                       # normal ElementTree install
                       import elementtree.ElementTree as etree
                       print("running with ElementTree")
                   except ImportError:
                       print("Failed to import ElementTree from any known place")
    
    document = etree.Element('outer')
    node = etree.SubElement(document, 'inner')
    print(etree.tostring(document, encoding='UTF-8', xml_declaration=True))
    
    0 讨论(0)
  • 2020-11-30 05:58

    xml_declaration Argument

    Is there a proper method for rendering the XML declaration in an ElementTree?

    YES, and there is no need of using .tostring function. According to ElementTree Documentation, you should create an ElementTree object, create Element and SubElements, set the tree's root, and finally use xml_declaration argument in .write function, so the declaration line is included in output file.

    You can do it this way:

    import xml.etree.ElementTree as ET
    
    tree = ET.ElementTree("tree")
    
    document = ET.Element("outer")
    node1 = ET.SubElement(document, "inner")
    node1.text = "text"
    
    tree._setroot(document)
    tree.write("./output.xml", encoding = "UTF-8", xml_declaration = True)  
    

    And the output file is:

    <?xml version='1.0' encoding='UTF-8'?>
    <outer><inner>text</inner></outer>
    
    0 讨论(0)
提交回复
热议问题