动态创建python函数

时间:2014-07-31 20:40:26

标签: python xml dynamic xml-parsing

我正在尝试使用Python解析10k行XML文件。该文件的摘录如下所示,描述了一长串元素的一些物理属性。每个元素都由XML文件中的" ble"我已经为每个" ble"编写了Python类。我会遇到的类型。

<header>
    <!--SlotModels-->
    <slotModels id="SpokeOptimusSlotModels" xml:base="spoke.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <slotModel id="spokeLEDP">
            <var id="g1" type="double"/>
            <ble id="DR0005" type="drift">
                <d id="l" type="double" unit="mm">240</d>
                <d id="r" type="double" unit="mm">20</d>
                <d id="ry" type="double" unit="mm">0</d>
            </ble>
            <ble id="QD0020" model="Quad310" type="quad">
                <d id="l" type="double" unit="mm">310</d>
                <d id="g" type="double" unit="T/m">g1</d>
                <d id="r" type="double" unit="mm">30</d>
            </ble>
        </slotModel>
        <slotModel id="spokeLwu">
            <var id="g1" type="double"/>
            <ble id="DR0010" type="drift">
                <d id="l" type="double" unit="mm">160</d>
                <d id="r" type="double" unit="mm">30</d>
                <d id="ry" type="double" unit="mm">0</d>
            </ble>
            <ble id="QD0020" model="Quad310" type="quad">
                <d id="l" type="double" unit="mm">310</d>
                <d id="g" type="double" unit="T/m">g1</d>
                <d id="r" type="double" unit="mm">30</d>
            </ble>
        </slotModel>
        <slotModel id="spokeCryomodule">
            <var id="xelmax1" type="double"/>
            <var id="rfpdeg1" type="double"/>
            <ble id="DR0010" type="drift">
                <d id="l" type="double" unit="mm">368.5</d>
                <d id="r" type="double" unit="mm">28</d>
                <d id="ry" type="double" unit="mm">0</d>
            </ble>
            <ble id="FM0020" model="spokeCavity" type="fieldMap">
                <d id="rfpdeg" type="double" unit="deg">rfpdeg1</d>
                <d id="xelmax" type="double" unit="unit">xelmax1</d>
                <d id="radiusmm" type="double" unit="mm">28</d>
                <d id="lengthmm" type="double" unit="mm">994</d>
                <d id="file" type="string" unit="unit">Spoke_F2F</d>
                <d id="scaleFactor" type="double" unit="unit">1.0</d>
            </ble>
        </slotModel>
    </slotModels>
    <slotModels id="medBetaSlotModels" xml:base="medBeta.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <slotModel id="medBetaLwu">
            <var id="g1" type="double"/>
            <ble id="DR0010" type="drift">
                <d id="l" type="double" unit="mm">256.2</d>
                <d id="r" type="double" unit="mm">50</d>
                <d id="ry" type="double" unit="mm">0</d>
            </ble>
            <ble id="QD0020" model="Quad410" type="quad">
                <d id="l" type="double" unit="mm">410</d>
                <d id="g" type="double" unit="T/m">g1</d>
                <d id="r" type="double" unit="mm">50</d>
            </ble>
        </slotModel>
        <slotModel id="medBetaCryomodule">
            <var id="xelmax1" type="double"/>
            <var id="rfpdeg1" type="double"/>
            <ble id="DR0010" type="drift">
                <d id="l" type="double" unit="mm">414.4</d>
                <d id="r" type="double" unit="mm">46.87</d>
                <d id="ry" type="double" unit="mm">0</d>
            </ble>
            <ble id="FM0020" model="medBetaCavity" type="fieldMap">
                <d id="rfpdeg" type="double" unit="deg">rfpdeg1</d>
                <d id="xelmax" type="double" unit="unit">xelmax1</d>
                <d id="radiusmm" type="double" unit="mm">46.87</d>
                <d id="lengthmm" type="double" unit="mm">1258.8</d>
                <d id="file" type="string" unit="unit">MB_F2F</d>
                <d id="scaleFactor" type="double" unit="unit">1.0</d>
            </ble>
        </slotModel>
    </slotModels>
    <cellModels id="SpokeOptimusCellModels" xml:base="spoke.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <cellModel id="spokeLEDPCell">
            <var id="g1" type="double"/>
            <var id="xelmax1" type="double"/>
            <var id="rfpdeg1" type="double"/>
            <slot id="slot010" model="spokeLEDP">
                <d id="g1" type="double">g1</d>
            </slot>
            <slot id="slot020" model="spokeCryomodule">
                <d id="xelmax1" type="double">xelmax1</d>
                <d id="rfpdeg1" type="double">rfpdeg1</d>
            </slot>
        </cellModel>
        <cellModel id="spokeCell">
            <var id="g1" type="double"/>
            <var id="xelmax1" type="double"/>
            <var id="rfpdeg1" type="double"/>
            <slot id="slot010" model="spokeLwu">
                <d id="g1" type="double">g1</d>
            </slot>
            <slot id="slot020" model="spokeCryomodule">
                <d id="xelmax1" type="double">xelmax1</d>
                <d id="rfpdeg1" type="double">rfpdeg1</d>
            </slot>
        </cellModel>
    </cellModels>
    <cellModels id="medBetaCellModels" xml:base="medBeta.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <cellModel id="medBetaCell">
            <var id="g1" type="double"/>
            <var id="xelmax1" type="double"/>
            <var id="rfpdeg1" type="double"/>
            <slot id="slot010" model="medBetaLwu">
                <d id="g1" type="double">g1</d>
            </slot>
            <slot id="slot020" model="medBetaCryomodule">
                <d id="xelmax1" type="double">xelmax1</d>
                <d id="rfpdeg1" type="double">rfpdeg1</d>
            </slot>
        </cellModel>
    </cellModels>
</header>
<linac>
    <section id="SPOK" rfHarmonic="1" xml:base="spoke.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <cell id="cell010" model="spokeLEDPCell">
            <d id="g1" type="double">5.23025</d>
            <d id="g2" type="double">-4.68975</d>
            <d id="xelmax1" type="double">0.868945</d>
            <d id="xelmax2" type="double">0.865525</d>
            <d id="rfpdeg1" type="double">-6.65943</d>
            <d id="rfpdeg2" type="double">4.03247</d>
        </cell>
        <cell id="cell020" model="spokeCell">
            <d id="g1" type="double">4.85226</d>
            <d id="g2" type="double">-4.77927</d>
            <d id="xelmax1" type="double">0.890626</d>
            <d id="xelmax2" type="double">0.891124</d>
            <d id="rfpdeg1" type="double">22.0298</d>
            <d id="rfpdeg2" type="double">31.6618</d>
        </cell>
        <cell id="cell030" model="spokeCell">
            <d id="g1" type="double">4.46164</d>
            <d id="g2" type="double">-4.45154</d>
            <d id="xelmax1" type="double">1</d>
            <d id="xelmax2" type="double">1</d>
            <d id="rfpdeg1" type="double">37.712</d>
            <d id="rfpdeg2" type="double">47.397</d>
        </cell>
    <!--SPOKE-->
    <section id="MBL" rfHarmonic="2" xml:base="medBeta.xml" xmlns:xi="http://www.w3.org/2001/XInclude">
        <cell id="cell010" model="medBetaCell">
            <d id="g1" type="double">3.39121</d>
            <d id="g2" type="double">-3.31534</d>
            <d id="xelmax1" type="double">0.44729</d>
            <d id="xelmax2" type="double">0.4477</d>
            <d id="xelmax3" type="double">0.453125</d>
            <d id="xelmax4" type="double">0.453307</d>
            <d id="rfpdeg1" type="double">55.8358</d>
            <d id="rfpdeg2" type="double">61.7858</d>
            <d id="rfpdeg3" type="double">66.1437</d>
            <d id="rfpdeg4" type="double">72.2867</d>
        </cell>
        <cell id="cell020" model="medBetaCell">
            <d id="g1" type="double">3.60124</d>
            <d id="g2" type="double">-3.64339</d>
            <d id="xelmax1" type="double">0.512886</d>
            <d id="xelmax2" type="double">0.512886</d>
            <d id="xelmax3" type="double">0.512886</d>
            <d id="xelmax4" type="double">0.512886</d>
            <d id="rfpdeg1" type="double">77.201</d>
            <d id="rfpdeg2" type="double">84.17</d>
            <d id="rfpdeg3" type="double">91.207</d>
            <d id="rfpdeg4" type="double">98.296</d>
        </cell>
    </section>
</linac>

请注意,XML文件的结构是&#34; slot&#34;和&#34;单元格&#34;,它们基本上是具有可辨别模式的ble列表,在标题中定义,而数据保存在&#34; linac&#34;。

我想做什么

我想扫描&#34; linac&#34;,然后将每个单元格扩展为我编写的类的完全实例化对象列表,以表示每个单元格。

为此,我希望能够以返回可以为每个slotModel或cellModel调用的函数的方式解析头。换句话说,我想自动生成如下函数:

def spokeLEDP(g1):
    bleList = []
    bleList.append(drift(l=240, r=20, ry=0)
    bleList.append(quad(l=310, g=g1, r=30)
    return bleList

def spokeLEDPcell(g1, xelmax1, rfpdeg1):
    myList = []
    myList.append(spokeLEDP(g1))
    myList.append(spokeCryomodule(xelmax1, rfpdeg1))
    return myList

我意识到我需要正确地压扁列表,但我希望你明白这个想法。

我的计划

我目前可以看到继续从标题中动态生成函数的唯一方法是两个步骤。首先,使用Python创建具有必要功能的文本文件。然后将其导入到工作代码中。

这看起来非常笨重而且笨拙。

我的问题

有没有办法在一步完成我想要做的事情,而不需要对&#34;单元格进行大量重复解析。和&#34;插槽&#34; XML标题中的元素?

非常感谢您阅读这篇文章,以及您可以提供的任何帮助。

(注意:我无法控制XML文件的结构。)

1 个答案:

答案 0 :(得分:1)

您可以使用DOM解析器路径为每个节点类型设置处理程序 - 基本上只访问每个节点,运行自定义代码等等。这是一种非常常见的模式。

有一些针对python的XML对象解决方案,没有一个是“很棒”,某些工作,其他的并不真正有用,但用心良好(或非常有限)。

一个相当模糊但有趣的包https://github.com/scieloorg/porteira 一个雄心勃勃的工作包是http://pyxb.sourceforge.net/,您可以根据模式进行“数据绑定”。这是正确的想法,但像大多数python XML包有一些粗略的边缘。我遇到了名称空间问题(对于大多数python项目而言,这可能是一个例子。如果你使用XSD和所有爵士乐进入超级硬核XML,那就更少了。

另一种解决方案是学习XPath并使用它来查询返回带有属性或字典的对象的结构。有很多方法可以给猫皮肤涂抹 - 希望我能给你一些潜在的解决方案。