![](/img/trans.png)
[英]python - sorting strings via xml attribute, .text malforms xml data
[英]Sorting the xml file based on xml text attribute
我有一個xml文件,其中的元素以某種隨機順序存在。 我必須比較這些文件,但由於元素順序的變化,需要手動操作。
我正在尋找一些方法來排序這些文件。 有人可以給我一些指針/解決這個問題的方法。 我嘗試閱讀lxml(ElementTree和Element類)的文檔,但似乎沒有一種方法可以根據xml文本對子元素進行排序。
我可以根據Name對元素進行排序,但在屬性元素中,如何對legal元素子進行排序?
輸入: -
<root>
<attribute Name="attr2">
<v>
<cstat>
<s>nObjDef2</s>
<s>nObjDef1</s>
</cstat>
</v>
<objects>
<legal>
<o>otype2</o>
<o>otype1</o>
</legal>
</objects>
</attribute>
<attribute Name="attr1">
<v>
<cstat>
<s>nObjDef2</s>
<s>nObjDef1</s>
</cstat>
</v>
<objects>
<legal>
<o>otype2</o>
<o>otype1</o>
</legal>
</objects>
</attribute>
</root>
預期產出:
<root>
<attribute Name="attr1">
<v>
<cstat>
<s>nObjDef1</s>
<s>nObjDef2</s>
</cstat>
</v>
<objects>
<legal>
<o>otype1</o>
<o>otype2</o>
</legal>
</objects>
</attribute>
<attribute Name="attr2">
<v>
<cstat>
<s>nObjDef1</s>
<s>nObjDef2</s>
</cstat>
</v>
<objects>
<legal>
<o>otype1</o>
<o>otype2</o>
</legal>
</objects>
</attribute>
</root>
如果要按文本對子項進行排序,只需找到合法節點並使用child.text作為鍵對子項進行排序:
x = """<root>
<attribute Name="attr2">
<v>
<cstat>
<s>nObjDef2</s>
<s>nObjDef1</s>
</cstat>
</v>
<objects>
<legal>
<o>otype2</o>
<o>otype1</o>
</legal>
</objects>
</attribute>
<attribute Name="attr1">
<v>
<cstat>
<s>nObjDef2</s>
<s>nObjDef1</s>
</cstat>
</v>
<objects>
<legal>
<o>otype2</o>
<o>otype1</o>
</legal>
</objects>
</attribute>
</root>
"""
要對每個節點進行排序:
from lxml import etree
xml = etree.fromstring(x)
for node in xml.xpath("//legal"):
node[:] = sorted(node, key=lambda ch: ch.text)
那將重新排序孩子:
print(etree.tostring(xml, pretty_print=1).decode("utf-8"))
給你:
<root>
<attribute Name="attr2">
<v>
<cstat>
<s>nObjDef2</s>
<s>nObjDef1</s>
</cstat>
</v>
<objects>
<legal>
<o>otype1</o>
<o>otype2</o>
</legal>
</objects>
</attribute>
<attribute Name="attr1">
<v>
<cstat>
<s>nObjDef2</s>
<s>nObjDef1</s>
</cstat>
</v>
<objects>
<legal>
<o>otype1</o>
<o>otype2</o>
</legal>
</objects>
</attribute>
</root>
或者更有效的方法,使用operator.attrgetter代替lambda:
from lxml import etree
from operator import attrgetter
xml = etree.fromstring(x)
for node in xml.xpath("//legal"):
node[:] = sorted(node, key=attrgetter("text"))
考慮XSLT ,這是專門用於操作和轉換XML文件的專用語言。 Python的lxml可以運行XSLT 1.0腳本。 具體來說,XSLT維護<xsl:sort>
方法,該方法可以在模板中運行:
import lxml.etree as et
# LOAD XML (FROM FILE) AND XSL (FROM STRING)
xml = et.parse('Input.xml')
xslstr = '''<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<!-- Identity Transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Sort Children Text of Nodes -->
<xsl:template match="cstat|legal">
<xsl:copy>
<xsl:apply-templates select="*">
<xsl:sort select="." order="ascending" data-type="text"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:transform>'''
xslt = et.fromstring(xslstr)
# TRANSFORM SOURCE TO NEW TREE
transform = et.XSLT(xslt)
newdom = transform(xml)
print(newdom)
# OUTPUT TO FILE
tree_out = et.tostring(newdom, encoding='UTF-8', pretty_print=True, xml_declaration=True)
xmlfile = open('Output.xml','wb')
xmlfile.write(tree_out)
xmlfile.close()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.