在使用python中的xml.etree.ElementTree库解析xml文件时, 节点的属性默认会被重新排序 。虽然xml文件节点属性顺序并没有什么实际意义,但有时在文件的可读性上会大打折扣。以高通平台小基站射频校准配置文件为例,笔者希望该xml文件的格式如下所示,这样很容易找出Tx、Rx、Nl等等射频链路的校准配置。

<?xml version='1.0' encoding='utf-8'?>
<CalConfigDefinitions>
	<BoardConfigs>
		<BoardDef name="F02001-2" configs="F02001-2_LTE20" />
	</BoardConfigs>
	<CalConfigs>
		<CalConfig name="F02001-2_LTE5" topology="407">
			<TxConfig txPathIdList="TX1,TX2" antennaNum="1,2" bwConst="LTE5" band="B41" fg="2" enableFb="false" txRefFreq="2590" listOfTxSweepFreqMhz="2498.5,2510.5,2520.5,2530.5,2540.5,2560.5,2580.5,2600.5,2620.5,2640.5,2660.5,2670.5,2680.5,2687.5" firstGainState="40" firstGainStatePowerLimitHigh="10" firstGainStatePowerLimitLow="-45" highestAllowedGainState="0" targetMaxPower="17" txDcLeakageLimit="-40" txIqImageLimit="-40" maxFreqSweepPeakToPeakDelta="10" rxFbDcLeakageLimitDbfs="-34" rxFbIqImageLimitDbc="-40" rxfbSignalDbfsMin="-20" rxfbSignalDbfsMax="0" txFreqSweepTargetReferencePowerDbm="17" txDigitalGainMaxDb="-3" txHighDcLeakageLimit="-43" txLowCutoffGainState="30" calDataAlsoAppliesTo="LTE10,LTE15,LTE20" txMonotonicCheckThresholdDb="-3" />
			<RxFb1AclrNoiseCal rxfbPathIdList="FB1,FB2" bwConst="LTE5" band="B41" fg="2" freq="2590" rxfbMaxGainState="16" />
			<RxConfig rxPathIdList="RX1,RX2" antennaNum="1,2" bwConst="LTE5" band="B41" fg="2" rxRefFreqMhz="2590" listOfRxSweepFreqMhz="2498.5,2510.5,2520.5,2530.5,2540.5,2560.5,2580.5,2600.5,2620.5,2640.5,2660.5,2670.5,2680.5,2687.5" rxGainStateList="0,1,2,3,4,5,6,7" rxSigGenPowersForGainState="-66,-59,-56,-51,-46,-41,-31,-21" rxDcLeakageLimitDbfs="-40" rxIqImageLimitDbc="-40" maxFreqSweepPeakToPeakDelta="10" rxSignalDbfsMin="-40" rxSignalDbfsMax="-20" calDataAlsoAppliesTo="LTE10,LTE15,LTE20" />
			<RxConfig rxPathIdList="NL1" antennaNum="3" bwConst="LTE20" band="B25" fg="3" rxRefFreqMhz="1960" listOfRxSweepFreqMhz="1930,1940,1945,1950,1955,1960,1965,1970,1975,1980,1985,1990,1995" rxGainStateList="0,1,2,3,4,5" rxSigGenPowersForGainState="-65,-57,-51,-40,-29,-18" rxDcLeakageLimitDbfs="-40" rxIqImageLimitDbc="-40" maxFreqSweepPeakToPeakDelta="10" rxSignalDbfsMin="-40" rxSignalDbfsMax="-20" />
		</CalConfig>
	</CalConfigs>
</CalConfigDefinitions>

笔者想实现自动生成该xml文件,但是当使用Python xml.etree.ElementTree库解析xml文件时,发现写入的节点属性顺序如下所示(默认修改成以字母排序),这样显得很混乱不易查找。下面来解决节点属性顺序变化的问题,读者不需要纠结该xml文件的实际意义,本文仅以此为例。

<?xml version='1.0' encoding='utf-8'?>
<CalConfigDefinitions>
	<BoardConfigs>
		<BoardDef configs="F02001-2_LTE20" name="F02001-2" />
	</BoardConfigs>
	<CalConfigs>
		<CalConfig name="F02001-2_LTE5" topology="407">
			<TxConfig antennaNum="1,2" band="B41" bwConst="LTE5" calDataAlsoAppliesTo="LTE10,LTE15,LTE20" enableFb="false" fg="2" firstGainState="40" firstGainStatePowerLimitHigh="10" firstGainStatePowerLimitLow="-45" highestAllowedGainState="0" listOfTxSweepFreqMhz="2498.5,2510.5,2520.5,2530.5,2540.5,2560.5,2580.5,2600.5,2620.5,2640.5,2660.5,2670.5,2680.5,2687.5" maxFreqSweepPeakToPeakDelta="10" rxFbDcLeakageLimitDbfs="-34" rxFbIqImageLimitDbc="-40" rxfbSignalDbfsMax="0" rxfbSignalDbfsMin="-20" targetMaxPower="17" txDcLeakageLimit="-40" txDigitalGainMaxDb="-3" txFreqSweepTargetReferencePowerDbm="17" txHighDcLeakageLimit="-43" txIqImageLimit="-40" txLowCutoffGainState="30" txMonotonicCheckThresholdDb="-3" txPathIdList="TX1,TX2" txRefFreq="2590" />
			<RxFb1AclrNoiseCal band="B41" bwConst="LTE5" fg="2" freq="2590" rxfbMaxGainState="16" rxfbPathIdList="FB1,FB2" />
			<RxConfig antennaNum="1,2" band="B41" bwConst="LTE5" calDataAlsoAppliesTo="LTE10,LTE15,LTE20" fg="2" listOfRxSweepFreqMhz="2498.5,2510.5,2520.5,2530.5,2540.5,2560.5,2580.5,2600.5,2620.5,2640.5,2660.5,2670.5,2680.5,2687.5" maxFreqSweepPeakToPeakDelta="10" rxDcLeakageLimitDbfs="-40" rxGainStateList="0,1,2,3,4,5,6,7" rxIqImageLimitDbc="-40" rxPathIdList="RX1,RX2" rxRefFreqMhz="2590" rxSigGenPowersForGainState="-66,-59,-56,-51,-46,-41,-31,-21" rxSignalDbfsMax="-20" rxSignalDbfsMin="-40" />
			<RxConfig antennaNum="3" band="B25" bwConst="LTE20" fg="3" listOfRxSweepFreqMhz="1930,1940,1945,1950,1955,1960,1965,1970,1975,1980,1985,1990,1995" maxFreqSweepPeakToPeakDelta="10" rxDcLeakageLimitDbfs="-40" rxGainStateList="0,1,2,3,4,5" rxIqImageLimitDbc="-40" rxPathIdList="NL1" rxRefFreqMhz="1960" rxSigGenPowersForGainState="-65,-57,-51,-40,-29,-18" rxSignalDbfsMax="-20" rxSignalDbfsMin="-40" />
		</CalConfig>
	</CalConfigs>
</CalConfigDefinitions>

软件环境说明

Python版本: Python 3.7
Xml解析库: xml.etree.ElementTree
IDE: PyCharm

节点属性自定义排序

笔者使用ElementTree类中的 write 方法生成xml文件,生成的tree中的节点属性顺序是自定义的,当写入文件时顺序就会发生变化,于是怀疑文件写入时默认对属性进行了排序。

查找ElementTree.py源码,发现 _serialize_xml 方法中果然对属性进行了排序,如下代码块所示(实际下文中并非 _serialize_xml 源码,在源码基础上对xml文件进行了部分缩进处理,读者可忽略此部分处理,如果感兴趣可以查看总结说明章节参考笔者的另一篇关于xml缩进处理的博客)。注释位置通过sorted方法对节点属性进行了词汇排序,使自定义顺序被打乱。

只需要修改这一行代码,将
for k, v in sorted(items):
改成
for k, v in items:
即可实现节点属性顺序的自定义。

def _serialize_xml(write, elem, qnames, namespaces,
                   short_empty_elements, level=1, **kwargs):
    tag = elem.tag
    text = elem.text
    if tag is Comment:
        write("<!--%s-->" % text)
    elif tag is ProcessingInstruction:
        write("<?%s?>" % text)
    else:
        tag = qnames[tag]
        if tag is None:
            if text:
                write(_escape_cdata(text))
            for e in elem:
                _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]):  		
                        if k:
                            k = ":" + k
                        write(" xmlns%s=\"%s\"" % (
                            _escape_attrib(v)
                for k, v in sorted(items):  		# ##### 将此行内容替换成  for k, v in items: 
                    if isinstance(k, QName):
                        k = k.text
                    if isinstance(v, QName):
                        v = qnames[v.text]
                    else:
                        v = _escape_attrib(v)
                    write(" %s=\"%s\"" % (qnames[k], v))
            if text or len(elem) or not short_empty_elements:
                write(">\n" + level * "\t")
                if text:
                    write(_escape_cdata(text))
                for e in elem:
                    _serialize_xml(write, e, qnames, None,
                                   short_empty_elements=short_empty_elements,level=level+1)
                write("</" + tag + ">")
            else:
                write(" />")
    if elem.tail:
        write(_escape_cdata(elem.tail))
  1. 文中引用的ElementTree.py中的代码并非源码,是添加了部分缩进处理之后的代码,源码生成的xml文件是没有任何缩进和换行处理的,读者大可不必纠结此部分差异。如果读者感兴趣,可以查看笔者的另一篇博客。
    Python解析xml文件: ElementTree解析xml换行和缩进美化问题

  2. 此文档仅用于Python学习记录和交流,如能帮助到读者倍感荣幸。

在使用python中的xml.etree.ElementTree库解析xml文件时,节点的属性默认会被重新排序。虽然xml文件节点属性顺序并没有什么实际意义,但有时在文件的可读性上会大打折扣。本文介绍如何通过修改ElementTree.py源码实现xml节点属性的自定义排序。 import xml.etree.ElementTree as ET def getTree(xmlName): xmlName = xmlName.strip() tree = ET.parse(xmlName) except: tree = None print 'Analysis xml file fail,file name: {}'.format(xmlName) return tree 2、获取根节点 def getRoot(tree): if tree is not None: root = tr <gdppc>141100</gdppc> <neighbor name=Austria direction=E/> <neighbor name=Switzerland direction=W/> </country> <country name=Singapore>
http://stackoverflow.com/questions/14257978/elementtree-setting-attribute-order Apply monkey patch as mentioned below::  in ElementTree.py file, there is a functionnamed as _serialize_xml;  in this
Python读写XML后保持节点属性顺序不变 试过xml.etree.ElementTreexml.dom.minidom两个python的库,发现读取后输出都会改变xml里面节点属性顺序. 虽然这个顺序其实没什么意义但是有些时候时候会比较纠结,找了好多资料最后在stackoverflow中找到一些有用的资料.最后亲测可用. 原资料地址 python环境:2.7 库:impor...
文章目录1. minidom 基础操作1.1 minidom 生成 xml 文件操作1.2 minidom 解析 xml 文件操作2. minidom在写入中存在的问题2.1 xml 文件时标签内属性排序问题2.2 生成 使用 minidom 读取节点后用节点写入时多余空行问题2.3 上述两个问题的解决方案, 在使用前重新封装写入文件的函数 1. minidom 基础操作 1.1 minidom 生成 xml 文件操作 1.2 minidom 解析 xml 文件操作 2. minidom在写入中存在的问题 观察到加入的顺序貌似是按照了数据title的首字母顺序内容来进行的排序,换了一台电脑运行后未出现这种情况,对比差异为python的版本差异,出现问题的电脑是3.6.1的版本 尝试进行如下测试 from xml.dom.minidom import Document doc = Document() dataRoot = do.
转发链接Python xml.etree.ElementTree读写xml文件实例 - 遐静草 - 博客园 本文通过实例讲解 Pythonxml.etree.ElementTree是如何读写,查找,修改,删除xml文件内容的。 以下例子基于如下xml 文件的内容 <name title="xml example">It is an xml example</name> <article name="My article"
本篇想从序列化开始,讲述pythonxml、json以及protobuf文件格式,并实现xml到json以及json到protobuf之间格式的互转与xml增删改查操作。另外关于ujson与bjson等格式类型,会在最后进行总结。 序列化与反序列化 互联网的产生带来了机器间通讯的需求,而互联通讯的双方需要采用约定的协议,序列化和反序列化属于通讯协议的一部分。通讯协议往往采用分层模型,不同模型每层的功能定义以及颗粒度不同,例如:TCP/IP协议是一个四层协议,而OSI模型却是七层协议模型。在OSI七
动态循环输出文字 print() 打印时会自动换行,无法实现刷新后在原位置显示内容,而 sys.stuout.write() 方法打印输出的时候自动删除前一步打印输出的内容,从而实现文字的循环动态显示 # _*_coding : UTF-8 _*_ import sys import time def print_arc(word): # 让光标回到行首 sys.stdout...
工作中需要把PPOCRLabel标注格式转化成需要的xml格式。 遇到的问题:1、之前只使用过使用minidom读xml,还没有使用过minidom写xml。2、minidom写xml顺序与写入的顺序不一致问题。 参考:Python3.7写入xml文件 保持节点属性顺序不变 首先导入模块 from xml.dom.minidom import Document,然后按下ctrl使用鼠标点击minidom进入源码 ctrl+F搜索a_names = sorted(attrs.keys())。...
### 回答1: PythonElementTree 模块是一种解析和操作 XML 文档的方式。您可以使用 ElementTree 读取 XML 文件,也可以使用 ElementTree 创建和修改 XML 文档。 以下是 ElementTree 解析 XML 的基本步骤: 1. 导入 ElementTree 模块。 2. 使用 ElementTree 的 parse() 函数打开 XML 文件。 3. 获取根元素。 4. 使用根元素的 find() 或 findall() 方法查找特定元素。 5. 使用元素的 attrib 属性获取元素的属性。 6. 使用元素的 text 属性获取元素的文本。 下面是一个使用 ElementTree 解析 XML 文件的示例代码: ```python import xml.etree.ElementTree as ET # 打开 XML 文件 tree = ET.parse('example.xml') # 获取根元素 root = tree.getroot() # 查找所有 country 元素 for country in root.findall('country'): # 获取 country 元素的属性 name = country.get('name') population = country.get('population') print(name, population) # 查找 country 元素下的 rank 元素 rank = country.find('rank') # 获取 rank 元素的文本 print(rank.text) 这是一个基本的示例代码,您可以根据您的需要进行更改和修改,以实现特定的 XML 解析和操作功能。 ### 回答2: Python ElementTreePython标准库中用于XML解析的模块,他提供了一个简单而有效的方法来解析XML文档并提取相关数据。PythonElementTreePython中提供了一种基于树型结构的解析方式,可以很简单的遍历整个XML文档。 ElementTree提供了Element类,该类代表XML元素。每个XML元素都有指定的标签、属性和子元素,可以使用ElementTreePython中很容易地解析和处理这些元素。 下面是Python ElementTree解析XML的一些常用方法: 1. parse()函数:使用此函数加载XML文件并将其转换为ElementTree对象。 2. Element()函数:使用此函数创建一个新的元素。 3. findall()函数:使用此函数查找所有匹配特定标签的元素。它将返回一个元素列表。 4. find()函数:使用此函数查找第一个匹配特定标签的元素。它将返回一个元素对象。 5. text属性:使用此属性访问元素标记中的文本内容。 6. attrib属性:使用此属性访问元素的属性字典。 7. tag属性:使用此属性访问元素的标签名称。 8. get()方法:使用此方法取得元素的特殊属性。 9. iter()函数:使用此函数可以遍历整个XML文档,一次处理每个元素。 总体而言,Python ElementTree提供了一种非常灵活和强大的方式来解析和处理XML文件。无论是处理大型的、复杂的XML文档,还是处理小型的、简单的XML文件Python ElementTree均能提供一种非常方便、易用和高效的解决方案。 ### 回答3: Python ElementTreePythonXML 解析库, 通过Python ElementTree, 可以轻松地解析和操作 XML 文件。本文将简要介绍如何使用Python ElementTree解析XML文件。 1. 解析XML文件Python中,可以使用ElementTree库的ElementTree.parse()方法解析XML文件,例如: import xml.etree.ElementTree as ET tree = ET.parse('filename.xml') root = tree.getroot() 通过以上代码,我们将XML文件tree对象的方式进行解析,并得到XML文件的根节点root。此时我们可以通过打印root节点,查看该文件的内部结构。 2. 获取节点数据 一旦我们已经解析XML,我们可以使用Python ElementTree库访问和操作树中的节点数据。最常用的方法即是通过节点的标签名称和属性来访问该节点: root = ET.fromstring(country_data_as_string) for child in root: print(child.tag, child.attrib) 在这个例子中,我们遍历了XML文档中所有节点,打印出它们的标签名称和属性。 3. 查找特定节点 有时候我们只需要获取XML文档中的特定节点。此时可以使用element.find()方法,该方法返回XML文档中tag名称与我们期望的相同的第一个元素。例如: root.find(".//rank/[@year='2011']") 上述代码中,我们使用XPath表达式在根元素之下查找rank元素,并使用一个特定的year属性值过滤这些元素。我们可以将输出与我们所期望的元素进行比较,以确定方法是否有效。 4. 修改XML文件 使用Python ElementTree库,我们可以轻松地修改XML文档中的数据并将其写回到文件中。例如,我们可以使用以下代码将内容写回到XML文件中: tree.write('filename.xml') 如果需要只写入更新后的XML元素,而不是完整的XML文档,则可以使用ElementTree.tostring()方法。例如: xml_string = ET.tostring(root) 在本文中,我们已经简要介绍了如何使用Python ElementTree解析XML和查找特定节点以及修改XML文件Python ElementTree是一个功能强大和灵活的XML解析库,可用于处理各种规模和类型的XML文件
CSDN-Ada助手: 非常感谢您分享这篇关于802.11-2020协议的学习笔记!您的知识分享将会帮助许多想要了解这方面知识的人。对于您提到的CCMP加密协议,我想建议您可以写一篇博客,深入解析CCMP的实现原理和安全性。对于安全这一话题,我们还可以探讨一些更实际的应用场景和防范方法。期待看到您的技术分享! 2023年博客之星「城市赛道」年中评选已开启(https://activity.csdn.net/creatActivity?id=10470&utm_source=blog_comment_city ), 博主的原力值在所在城市已经名列前茅,持续创作就有机会成为所在城市的 TOP1 博主(https://bbs.csdn.net/forums/blogstar2023?typeId=3152981&utm_source=blog_comment_city),更有丰厚奖品等你来拿~。 Python解析xml文件: ElementTree解析xml节点属性排序问题 回笼觉觉父: 好哒,不好意思刚看到表情包 Python解析xml文件: ElementTree解析xml节点属性排序问题 找到啦,谢谢博主 Python解析xml文件: ElementTree解析xml节点属性排序问题 请问怎么才能修改那个源码呀