我正试图用lxml创建一个xml文件,我很清楚xml中属性的顺序并不重要,但我还是在寻找一种方法来防止属性按特定顺序排列。
我也试过minidom,但也没有成功。
在lxml中,我有以下代码。
from lxml import etree as ET
from collections import OrderedDict
root = ET.Element("Root", OrderedDict([("id","0"),("start","0"),("end","200")]))
ET.tostring(root)
这一部分给出了下面的结果,其中的属性按照我想要的顺序排列,因为我在这里使用了OrderedDict。
<Root id="0" start="0" end="200"/>
然后我用同样的方法创建了一个Child。
child1 = ET.Element("sentence", OrderedDict([("id","0"),("start","0"),("end","255")]))
root.append(child1)
xml_str = ET.tostring(root, pretty_print=True)
print(xml_str)
打印xml_str的输出结果符合我的期望。
<Root id="0" start="0" end="200">\n <sentence id="0" start="0" end="255"/>\n</Root>
但是当我把它写到xml文件中时:
with open('op.xml', 'wb') as f:
f.write(xml_str)
写到op.xml文件中的输出就不一样了。
<?xml version="1.0"?>
<Root end="200" start="0" id="0">
<sentence end="255" start="0" id="0"/>
</Root>
明明看到属性顺序已经改变了,有什么办法可以让输出结果和我期望的一样,即属性顺序得到保持。
我也试过用minidom,但也没有用,即使参考了。用minidom修改时保留属性顺序。
这里有一个库,擅长提取数据,不太擅长修改xml文件,但也基本能满足你的需求。
from simplified_scrapy import SimplifiedDoc, utils, req
doc = SimplifiedDoc("<Root></Root>")
doc.Root.setAttrs({"id":"0","start":"0","end":"200"})
doc.Root.setContent("<sentence />")
doc.sentence.setAttrs({"id":"0","start":"0","end":"200"})
utils.saveFile("op.xml",doc.html)
结果。
<Root id="0" start="0" end="200"><sentence id="0" start="0" end="200" /></Root>
用lxml.etree就可以了。
import lxml.etree
from collections import OrderedDict
root = lxml.etree.Element("Root", OrderedDict([("id","0"),("start","0"),("end","200")]))
isVal = lxml.etree.SubElement(root, 'sentence', OrderedDict([("id","0"),("start","0"),("end","255")]))
with open("xyz2.xml", 'wb') as f:
f.write(lxml.etree.tostring(root, xml_declaration=True, encoding="utf-8"))
print(open("xyz2.xml", 'r').read())
输出:
<?xml version='1.0' encoding='utf-8'?>
<Root id="0" start="0" end="200"><sentence id="0" start="0" end="255"/></Root>