使用 XML ElementTree 创建具有属性的对象列表

Using XML ElementTree to create list of objects with atrributes

我使用 python 请求模块从 TeamCity rest api 中获取 XML,如下所示:

<triggers count="10">
<trigger id="TRIGGER_1240" type="buildDependencyTrigger">
    <properties count="2">
        <property name="afterSuccessfulBuildOnly" value="true"/>
        <property name="dependsOn" value="bt191"/>
    </properties>
</trigger>
<trigger id="TRIGGER_1241" type="buildDependencyTrigger">
    <properties count="2">
        <property name="afterSuccessfulBuildOnly" value="true"/>
        <property name="dependsOn" value="bt171"/>
    </properties>
</trigger>
<trigger id="TRIGGER_1242" type="buildDependencyTrigger">
    <properties count="2">
        <property name="afterSuccessfulBuildOnly" value="true"/>
        <property name="dependsOn" value="bt167"/>
    </properties>
</trigger>
<trigger id="TRIGGER_1243" type="buildDependencyTrigger">
    <properties count="2">
        <property name="afterSuccessfulBuildOnly" value="true"/>
        <property name="dependsOn" value="bt164"/>
    </properties>
</trigger>
<trigger id="TRIGGER_1244" type="buildDependencyTrigger">
    <properties count="2">
        <property name="afterSuccessfulBuildOnly" value="true"/>
        <property name="dependsOn" value="bt364"/>
    </properties>
</trigger>
<trigger id="TRIGGER_736" type="buildDependencyTrigger">
    <properties count="2">
        <property name="afterSuccessfulBuildOnly" value="true"/>
        <property name="dependsOn" value="Components_Ratchetdb"/>
    </properties>
</trigger>
<trigger id="TRIGGER_149" type="buildDependencyTrigger">
    <properties count="2">
        <property name="afterSuccessfulBuildOnly" value="true"/>
        <property name="dependsOn" value="Components_Filedb"/>
    </properties>
</trigger>
<trigger id="TRIGGER_150" type="buildDependencyTrigger">
    <properties count="2">
        <property name="afterSuccessfulBuildOnly" value="true"/>
        <property name="dependsOn" value="bt168"/>
    </properties>
</trigger>
<trigger id="TRIGGER_1130" type="buildDependencyTrigger">
    <properties count="2">
        <property name="afterSuccessfulBuildOnly" value="true"/>
        <property name="dependsOn" value="Components_Tbldb"/>
    </properties>
</trigger>
<trigger id="vcsTrigger" type="vcsTrigger" inherited="true">
    <properties count="3">
        <property name="quietPeriod" value="60"/>
        <property name="quietPeriodMode" value="USE_DEFAULT"/>
        <property name="triggerRules" value="-:version.properties&#xA;-:comment=^Incremented:**&#xA;-:**/*-schema.sql"/>
    </properties>
</trigger>

我正在尝试使用 class 创建 "trigger" 个对象的列表。理想情况下,该对象将具有 id、类型和属性属性列表作为 {name : value} 的字典。到目前为止我的代码是:

class triggerList:
     def __init__(self, triggerId, triggerType):
         self.id = triggerId
         self.type = triggerType
         self.properties = []

     def add_property(self, buildProperty):
         self.properties.append(buildProperty)

def getAllTriggers(buildId):
     url = path + 'buildTypes/id:' + buildId + '/triggers'
     r = requests.get(url, auth=auth)
     tree = ElementTree.fromstring(r.content)
     listOfTriggers = []

     for trigger in tree.iter('trigger'):
         triggerType = trigger.get('type')
         triggerId = trigger.get('id')
         triggerName = str(triggerId)
         triggerName = triggerList(triggerId, triggerType)
         listOfTriggers.append(triggerName)

         for triggerProperty in tree.iter('property'):
             propertyName = triggerProperty.get('name')
             propertyValue = triggerProperty.get('value')
             propDict = {propertyName : propertyValue}
             triggerName.add_property(propDict)

这给了我一个对象列表,但每个对象都有每个 属性 字典的列表。这是输出:

a = listOfTriggers[1]
print a.id, a.type, a.properties

>>>  TRIGGER_1241 buildDependencyTrigger [{'afterSuccessfulBuildOnly': 'true'}, {'dependsOn': 'bt191'}, {'afterSuccessfulBuildOnly': 'true'}, {'dependsOn': 'bt171'}, {'afterSuccessfulBuildOnly': 'true'}, {'dependsOn': 'bt167'}, {'afterSuccessfulBuildOnly': 'true'}, {'dependsOn': 'bt164'}, {'afterSuccessfulBuildOnly': 'true'}, {'dependsOn': 'bt364'}, {'afterSuccessfulBuildOnly': 'true'}, {'dependsOn': 'Components_Ratchetdb'}, {'afterSuccessfulBuildOnly': 'true'}, {'dependsOn': 'Components_Filedb'}, {'afterSuccessfulBuildOnly': 'true'}, {'dependsOn': 'bt168'}, {'afterSuccessfulBuildOnly': 'true'}, {'dependsOn': 'Components_Tbldb'}, {'quietPeriod': '60'}, {'quietPeriodMode': 'USE_DEFAULT'}, {'triggerRules': '-:version.properties\n-:comment=^Incremented:**\n-:**/*-schema.sql'}]

我不知道如何仅针对特定触发器的属性停止循环。有没有办法使用 ElementTree 只获取特定触发器的属性?有没有更有效的方法来创建这个对象?

没有直接回答问题,但你可能在这里重新发明轮子,检查lxml.objectify package:

The main idea is to hide the usage of XML behind normal Python objects, sometimes referred to as data-binding. It allows you to use XML as if you were dealing with a normal Python object hierarchy. Accessing the children of an XML element deploys object attribute access. If there are multiple children with the same name, slicing and indexing can be used. Python data types are extracted from XML content automatically and made available to the normal Python operators.

简单的语法错误:

for triggerProperty in trigger.iter('property'):
        propertyName = triggerProperty.get('name')
        propertyValue = triggerProperty.get('value')
        propDict = {propertyName : propertyValue}
        triggerName.add_property(propDict)

我正在遍历整个树,而不是触发器。应该是:

for triggerProperty in trigger.iter('property'):