根据节点值

时间:2016-09-24 22:14:36

标签: python xml python-2.7 xslt xslt-2.0

我试图比较两个具有相同内容但有时在不同行上的XML文件。为了克服这个问题,我试图在其中一个子节点上对XML进行排序(这两个节点的位置通常不同)。

这是我的示例XML文件

<Report>
<rptName>Sample</rptName>
<reportNameGrp>
<grpName>AggrDataSet</grpName>
<RC>
<rptSubHdr>
<membLglNam>Registered Customer 103</membLglNam>
<membId>RC103</membId>
<relCM>CM022</relCM>
</rptSubHdr>
</RC>
<RC>
<rptSubHdr>
<membLglNam>Registered Customer 055</membLglNam>
<membId>RC055</membId>
<relCM>CM022</relCM>
</rptSubHdr>
</RC>
<RC>
<rptSubHdr>
<membLglNam>Registered Customer 047</membLglNam>
<membId>RC047</membId>
<relCM>CM022</relCM>
</rptSubHdr>
</RC>
<RC>
<rptSubHdr>
<membLglNam>Registered Customer 015</membLglNam>
<membId>RC015</membId>
<relCM>CM022</relCM>
</rptSubHdr>
</RC>
<RC>
<rptSubHdr>
<membLglNam>Registered Customer 024</membLglNam>
<membId>RC024</membId>
<relCM>CM022</relCM>
</rptSubHdr>
</RC>
</reportNameGrp>
</Report>

我正在尝试基于<membId>父节点的<RC>节点进行排序。无论我尝试什么方法,我的文档都无法排序。我尝试使用XSLT,但排序不起作用。我甚至尝试编写python脚本,但无法排序。

这是我的python脚本 -

import sys
from lxml import etree

filename, tag = sys.argv[1:]

doc = etree.parse(filename, etree.XMLParser(remove_blank_text=True))
root = doc.getroot()
root[:] = sorted(root, key=lambda el: el.findtext(tag))
print etree.tostring(doc, pretty_print=True)

我执行python test.py 2.xml membId来运行脚本(请注意2.xml是输入xml的文件名,membId是我要查找的标记)。

我真的很感激我在哪里出错了。我刚开始使用Python,所以我可能犯了一些非常明显的错误。 python脚本或XSLT解决方案(或者)对我有用!

1 个答案:

答案 0 :(得分:2)

考虑使用Python lxml集成的以下XSLT脚本。此外,您尝试运行动态命令行进程。不幸的是,XSLT将根据您要排序的特定节点在结构上发生变化。下面将按升序对<membId>进行专门排序:

<强> XSLT

<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 MembId under RC/rptSubHdr -->
  <xsl:template match="reportNameGrp">
    <xsl:copy>      
        <xsl:copy-of select="grpName"/>
        <xsl:apply-templates select="RC">          
            <xsl:sort select="rptSubHdr/membId" order="ascending"/>
        </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

</xsl:transform>

<强>的Python

import lxml.etree as et

// LOAD XML AND XSL SOURCES
dom = et.parse('Input.xml')
xslt = et.parse('XSLTScript.xsl')

// TRANSFORM
transform = et.XSLT(xslt)
newdom = transform(dom)

// SAVE TO FILE
with open('Output.xml', 'wb') as f:
    f.write(newdom)