Python XML - 从动态嵌套的 "node"元素构建平面记录

标签 python xml elementtree

我需要解析 XML 文件并根据数据构建基于记录的输出。问题在于 XML 是一种“通用”形式,因为它具有表示某种数据结构的多层嵌套“节点”元素。我需要根据“节点”元素的最深层动态构建记录。一些示例 XML 和预期输出位于底部。

我最熟悉 python 的 ElementTree,所以我更愿意使用它,但我就是想不出一种基于动态节点深度动态构建输出记录的方法。此外 - 我们不能假设嵌套节点将有 x 层深,因此不可能仅使用循环对每个层进行硬编码。有没有一种方法可以解析 XML 并动态构建输出?

一些附加说明:

  • 除了父级和详细信息(费率、价格等)外,节点名称均为“节点”
  • 节点深度不是静态的。所以 - 假设比样本中显示的水平更高
  • 每个“级别”可以有多个子级别。所以 - 您需要在每个子“节点”上循环以正确构建每条记录。

任何想法/意见将不胜感激。

<root>
   <node>101
      <node>A
         <node>PlanA     
            <node>default
                <rate>100.00</rate>
            </node>
            <node>alternative
                <rate>90.00</rate>
            </node>
         </node>
      </node>
   </node>
   <node>102
      <node>B
         <node>PlanZZ     
            <node>Group 1
               <node>default
                   <rate>100.00</rate>
               </node>
               <node>alternative
                   <rate>90.00</rate>
               </node>
            </node>
            <node>Group 2
               <node>Suba
                  <node>default
                      <rate>1.00</rate>
                  </node>
                      <node>alternative
                      <rate>88.00</rate>
                  </node>
               </node>
               <node>Subb
                  <node>default
                      <rate>200.00</rate>
                  </node>
                      <node>alternative
                      <rate>4.00</rate>
                  </node>
               </node>
            </node>
         </node>
      </node>  
   </node>
</root>

输出看起来像这样:

SRV  SUB  PLAN   Group    SubGrp  DefRate   AltRate
101  A    PlanA                   100       90
102  B    PlanB  Group1           100       90
102  B    PlanB  Group2   Suba    1         88
102  B    PlanB  Group2   Subb    200       4

最佳答案

这就是为什么您有 Element Tree find 方法和 XPath。

class Plan( object ):
    def __init__( self ):
        self.srv= None
        self.sub= None
        self.plan= None
        self.group= None
        self.subgroup= None
        self.defrate= None
        self.altrate= None
    def initFrom( self, other ):
        self.srv= other.srv
        self.sub= other.sub
        self.plan= other.plan
        self.group= other.group
        self.subgroup= other.subgroup
    def __str__( self ):
        return "%s %s %s %s %s %s %s" % (
            self.srv, self.sub, self.plan, self.group, self.subgroup,
            self.defrate, self.altrate )

def setRates( obj, aSearch ):
    for rate in aSearch:
        if rate.text.strip() == "default":
            obj.defrate= rate.find("rate").text.strip()
        elif rate.text.strip() == "alternative":
            obj.altrate= rate.find("rate").text.strip()
        else:
            raise Exception( "Unexpected Structure" )

def planIter( doc ):
    for topNode in doc.findall( "node" ):
        obj= Plan()
        obj.srv= topNode.text.strip()
        subNode= topNode.find("node")
        obj.sub= subNode.text.strip()
        planNode= topNode.find("node/node")
        obj.plan= planNode.text.strip()
        l3= topNode.find("node/node/node")
        if l3.text.strip() in ( "default", "alternative" ):
            setRates( obj, topNode.findall("node/node/node") )
            yield obj
        else:
            for group in topNode.findall("node/node/node"):
                grpObj= Plan()
                grpObj.initFrom( obj )
                grpObj.group= group.text.strip()
                l4= group.find( "node" )
                if l4.text.strip() in ( "default", "alternative" ):
                    setRates( grpObj, group.findall( "node" ) )
                    yield grpObj
                else:
                    for subgroup in group.findall("node"):
                        subgrpObj= Plan()
                        subgrpObj.initFrom( grpObj )
                        subgrpObj.subgroup= subgroup.text.strip()
                        setRates( subgrpObj, subgroup.findall("node") )
                        yield subgrpObj

import xml.etree.ElementTree as xml
doc = xml.XML( doc )

for plan in planIter( doc ):
    print plan

编辑

给你这份 XML 文档的人需要另找工作。这是一件坏事 (TM),表示对 XML 含义的相当随意的忽视。

关于Python XML - 从动态嵌套的 "node"元素构建平面记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/689339/

相关文章:

python - 从列表中获取键和值

python - 如何更改梅尔谱图的大小?

python - 如何从我的 kivy 应用程序(Pyinstaller)获取 Windows 可执行文件?

java - 如何调整 JAXB 生成 Java 模型以获得我想要的 Java 代码?

javascript - XMLHttpRequest 响应XML 始终为 null

python - 如何迭代解析 zipfile 对象

python - 为什么 Python 尝试自动编码我的 Unicode 字符串?

javascript - 我如何使用 jQuery 的 .find 方法并以正则表达式作为参数?

python-2.7 - 使用Python ElementTree.register_namespace读取GPX?

python - 更改 lxml 中的元素命名空间