我有一个XML编写脚本,可以为特定的第三方工具输出XML.
我使用原始XML作为模板来确保我正在构建所有正确的元素,但最终的XML看起来并不像原始的那样.
我以相同的顺序编写属性,但lxml按自己的顺序编写它们.
我不确定,但我怀疑第3部分工具希望属性以特定顺序出现,我想解决这个问题,这样我就可以看到它的attrib命令是否会失败,或者其他什么.
来源要素:
<FileFormat ID="1" Name="Development Signature" PUID="dev/1" Version="1.0" MIMEType="text/x-test-signature">
Run Code Online (Sandbox Code Playgroud)
我的源脚本:
sig.fileformat = etree.SubElement(sig.fileformats, "FileFormat", ID = str(db.ID), Name = db.name, PUID="fileSig/{}".format(str(db.ID)), Version = "", MIMEType = "")
Run Code Online (Sandbox Code Playgroud)
我的结果XML:
<FileFormat MIMEType="" PUID="fileSig/19" Version="" Name="Printer Info File" ID="19">
Run Code Online (Sandbox Code Playgroud)
有没有办法限制他们写的顺序?
Dan*_*l K 16
从lxml 3.3.3开始(也许在早期版本中),您可以将OrderedDict属性传递给lxml.etree.(Sub)Element构造函数,并且在使用时将保留顺序lxml.etree.tostring(root):
sig.fileformat = etree.SubElement(sig.fileformats, "FileFormat", OrderedDict([("ID",str(db.ID)), ("Name",db.name), ("PUID","fileSig/{}".format(str(db.ID))), ("Version",""), ("MIMEType","")]))
Run Code Online (Sandbox Code Playgroud)
需要注意的是,ElementTree的API( xml.etree.ElementTree)并不会保留属性顺序,即使你提供了一个OrderedDict在xml.etree.ElementTree.(Sub)Element构造函数!
更新:另外请注意,使用**extra该参数lxml.etree.(Sub)Element的构造函数用于指定属性并不会保留属性顺序:
>>> from lxml.etree import Element, tostring
>>> from collections import OrderedDict
>>> root = Element("root", OrderedDict([("b","1"),("a","2")])) # attrib parameter
>>> tostring(root)
b'<root b="1" a="2"/>' # preserved
>>> root = Element("root", b="1", a="2") # **extra parameter
>>> tostring(root)
b'<root a="2" b="1"/>' # not preserved
Run Code Online (Sandbox Code Playgroud)
Mar*_*nas 15
看起来lxml按照您设置的顺序序列化属性:
>>> from lxml import etree as ET
>>> x = ET.Element("x")
>>> x.set('a', '1')
>>> x.set('b', '2')
>>> ET.tostring(x)
'<x a="1" b="2"/>'
>>> y= ET.Element("y")
>>> y.set('b', '2')
>>> y.set('a', '1')
>>> ET.tostring(y)
'<y b="2" a="1"/>'
Run Code Online (Sandbox Code Playgroud)
请注意,使用ET.SubElement()构造函数传递属性时,Python会构造关键字参数的字典并将该字典传递给lxml.这会丢失源文件中的任何顺序,因为Python的字典是无序的(或者说,它们的顺序由字符串哈希值决定,字符串哈希值可能因平台而异,或者实际上从执行到执行不同).
属性排序和可读性 正如评论者所提到的,属性顺序在XML中没有语义意义,也就是说它不会改变元素的含义:
<tag attr1="val1" attr2="val2"/>
<!-- means the same thing as: -->
<tag attr2="val2" attr1="val1"/>
Run Code Online (Sandbox Code Playgroud)
SQL中有一个类似的特性,其中列顺序不会改变表定义的含义.XML属性和SQL列是一个集合 (不是有序集合),因此关于其中任何一个都可以"正式"说出的是该集合中是否存在属性或列.
也就是说,它肯定会对人类的可读性产生影响,这些事情的顺序会出现在这样的结构中,在这种情况下,这样的结构被创作并出现在文本中(例如源代码)并且必须被解释,仔细的排序对我来说很有意义.
典型的解析器行为
任何将属性顺序视为重要的XML解析器都将不符合XML标准.这并不意味着它不会发生,但根据我的经验,它肯定是不寻常的.不过,根据您提到的工具的证据,这可能值得测试.
据我所知,lxml没有机制来指定序列化XML中出现的顺序属性,如果有的话我会感到惊讶.
为了测试行为,我强烈倾向于编写一个基于文本的模板来生成足够的XML来测试它:
id = 1
name = 'Development Signature'
puid = 'dev/1'
version = '1.0'
mimetype = 'text/x-test-signature'
template = ('<FileFormat ID="%d" Name="%s" PUID="%s" Version="%s" '
'MIMEType="%s">')
xml = template % (id, name, puid, version, mimetype)
Run Code Online (Sandbox Code Playgroud)