Date:
2010-10-17
別解: lxmlを使ってXMLの要素をソートして返す¶
はじめに¶
こんにちは、NERDです。先日、 lxmlを使ってXMLの要素をソートして返す - YAMAGUCHI::weblog というエントリが上がっていたので、XMLの変換と言えばxsltでしょう!とか思ったので実際にやってみました。xsltの適用は元記事の方でも使っているlxmlで簡単にできるのが良いですね。
参考¶
サンプルコード¶
# -*- coding: utf-8 -*-
from lxml import etree
xml = """
<statuses>
<status>
<id>5</id>
<text>spam</text>
</status>
<status>
<id>1</id>
<text>egg</text>
</status>
<status>
<id>100</id>
<text>ham</text>
</status>
<status>
<id>2</id>
<text>bacon</text>
</status>
</statuses>
"""
xslt = """
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/statuses">
<xsl:copy>
<xsl:for-each select="status">
<xsl:sort select="id" data-type="number" />
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
"""
def sort_by_id(xml):
try:
tree = etree.fromstring(xml)
transform = etree.XSLT(etree.fromstring(xslt))
transformed = transform(tree)
return etree.tostring(transformed, pretty_print=True)
except Exception, e:
"""
rescure here.
"""
raise e
if __name__ == '__main__':
print xml
print '--------------------'
print sort_by_id(xml)
xsltの記述、けっこう長くなってしまってますね。もうちょっと短く書ける気がするんですが…。あと出来るだけタグ名に依存しないように書ければいいなあ。
実行結果¶
<statuses>
<status>
<id>5</id>
<text>spam</text>
</status>
<status>
<id>1</id>
<text>egg</text>
</status>
<status>
<id>100</id>
<text>ham</text>
</status>
<status>
<id>2</id>
<text>bacon</text>
</status>
</statuses>
--------------------
<statuses>
<status>
<id>1</id>
<text>egg</text>
</status>
<status>
<id>2</id>
<text>bacon</text>
</status>
<status>
<id>5</id>
<text>spam</text>
</status>
<status>
<id>100</id>
<text>ham</text>
</status>
</statuses>