2012-07-23 99 views
1

是否有可能XML文件,如排序如下:排序XML文件

<model name="ford"> 
<driver>Bob</driver> 
<driver>Alice</driver> 
</model> 

<model name="audi"> 
<driver>Carly</driver> 
<driver>Dean</driver> 
</model> 

这将成为

<model name="audi"> 
<driver>Carly</driver> 
<driver>Dean</driver> 
</model> 

<model name="ford"> 
<driver>Alice</driver> 
<driver>Bob</driver> 
</model> 

也就是说,最外层的元素会先被排序,然后是第二最外面,和等等。

他们需要先按元素名称排序。这可以做到吗?或者我应该使用像BeautifulSoup这样的东西来旋转我自己的东西?

+1

将结构读入对象列表中,对其进行排序,然后将其写回到任意位置。就这么简单。我不认为这里的人会为你写代码。 – MMM 2012-07-23 10:34:28

+0

我希望能有这样的东西。这将节省重新发明轮子。 – Rory 2012-07-23 10:35:00

+1

对xml进行排序没有意义,但可以使用xslt对其进行转换。 [看到这个](http://www.w3schools.com/xsl/xsl_sort.asp) – Takahiro 2012-07-23 10:35:37

回答

4

这是基里尔的解决方案的改进,我认为它能更好地反映规定的要求,并避免了错误类型XSLT 2.0将会给你,如果排序关键字包含多个值(但它仍然适用于1.0)。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" /> 

    <xsl:template match="*"> 
    <xsl:copy> 
    <xsl:copy-of select="@*"/> 
    <xsl:apply-templates select="*"> 
     <xsl:sort select="(@name | text())[1]"/> 
    </xsl:apply-templates> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 
+0

嗨,xslt中是否有拼写错误:需要成为起始标记,而不是完整标记(匹配的结束标记在文件中较低两行) – 2016-02-11 11:49:38

+0

已修复。 ----------- – 2016-02-11 21:22:35

1

试试这个XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" /> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
    <xsl:apply-templates select="@* | node()"> 
     <xsl:sort select="text() | @*"/> 
     </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+2

它的工作原理,但只是偶然,看起来比它更普遍。例如,它仅适用于具有子元素的元素只有一个属性。 – 2012-07-23 11:08:21

0

你并不需要梳理整个XML DOM。 而是将所需的节点放入列表中并对其进行排序。因为在处理时我们需要排序的顺序,而不是在文件中,所以在运行时更好。 可能是这样的,使用minidom。

import os, sys 
from xml.dom import minidom 
document = """\ 
<root> 
<model name="ford"> 
<driver>Bob</driver> 
<driver>Alice</driver> 
</model><model name="audi"> 
<driver>Carly</driver> 
<driver>Dean</driver> 
</model> 
</root> 
""" 

document = minidom.parseString(document) 
elements = document.getElementsByTagName("model") 
elements.sort(key=lambda elements:elements.attributes['name']) 
0

您可以通过将节点从父节点中删除并按照预定顺序重新插入节点来排序节点。例如:

def sort_tree(tree): 
    """ recursively sorts the given etree in place """ 
    for child in tree: 
     sort_tree(child) 

    sorted_children = sorted(tree, key=lambda n: n.text) 
    for child in tree: 
     tree.remove(child) 
    for child in reversed(sorted_children): 
     tree.insert(0, child) 

tree = etree.fromstring(YOUR_XML) 
sort_tree(tree) 
print(etree.tostring(tree, pretty_print=True))