簡體   English   中英

基於xml文本屬性對xml文件進行排序

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM