Python和ElementTree:如何在XML中嵌套元素/子元素?

2024-04-19 15:51:03 发布

您现在位置:Python中文网/ 问答频道 /正文

背景

我正在使用python2.6、ElementTree和SQLite3。我的脚本当前执行以下操作:

  • 连接到数据库以从表/架构中检索信息
  • 向XML树添加必要的数据
  • 输出(当前不正确)XML文件

代码

下面是我如何检索模式数据并将元素添加到XML中。我对SOFTWARE_TARGET_表执行此操作。这是SOFTWARE_表:

software_attributes =  ["id", "functionalDesignationHardware", "hwfin", "identname", "partnumber",
                        "repfin", "targetHardwareID"]

software = db.cursor().execute("SELECT %s from SOFTWARE_" % ", ".join([i + "_" for i in software_attributes]))
software_Data = software.fetchall()
ID1 = db.cursor().execute("SELECT id_ from SOFTWARE_")
software_IDs = ID1.fetchall()

for sw in software_Data:
   sw_node = ET.SubElement(root, "Software")
   for s in range(1, len(software_attributes)):
      sw_node.set(software_attributes[s], str(sw[s]))

更新:这是我的TARGET_表的代码:

^{pr2}$

这就是我如何存储表中的信息,这些表的唯一目的是连接来自其他表的数据。SOFTWARE_TARGET_表将SOFTWARE_连接到TARGET_。我把它的信息储存在字典里:

software_target = db.cursor().execute("SELECT SOFTWARE1, TARGET2 from SOFTWARE_TARGET_")
software_target_Data = software_target.fetchall()

# Map SOFTWARE1 to TARGET2
separated_st_Data = {}
for item in software_target_Data:
    software1, target2 = item
    try:
        separated_st_Data[software1].append(target2)
    except KeyError:
        separated_st_Data[software1] = [target2]

尝试

到目前为止,我已经找到了如何将xml设置为以下格式:

<Software attribute="stuff" attribute2="Stuff"/>
<Software attribute="stuff" attribute2="Stuff"/>
<Target attribute="things" attribute2="Things"/>

但我需要的是以下格式:

<Software attribute="stuff" attribute2="Stuff"
    <Target attribute="things" attribute2="Things"/>
    <Target attribute="things" attribute2="Things"/>
</Software>
<Software attribute="stuff" attribute2="Stuff"/>

哪个Target子元素位于哪个Software元素之下,由SOFTWARE_TARGET_表中的信息确定。我找到了如何遍历我的字典,比如:

depth=0
for k,v in sorted(separated_st_Data.items(),key=lambda x: x[0]):
    if isinstance(v, dict):
        print ("  ")*depth + ("%s" % k)
        walk_dict(v,depth+1)
    else:
        print ("  ")*depth + "%s %s" % (k, v)

问题

如何根据数据库表中的信息创建格式正确的XML文件(如尝试部分所述)?我创造了这本词典,以为我可以用它来达到这个目的——如果有必要,请告诉我。在


注意事项

This是我从SOFTWARE_TARGET_表创建的字典的样子。键表示来自SOFTWARE_id_模式,值表示来自TARGET_id_模式。(如果我的术语听起来不符合要求,请告诉我-数据库有时会让我困惑)。在


Tags: in信息idtargetfordataattributesoftware
2条回答

喔,几乎忘了-下面是我在完成的Python脚本中使用的最终代码(当然,除了完整脚本的几个关键元素):

software_attributes =  ["id", "partnumber", "identname", "functionalDesignationHardware", "hwfin", 
                        "targetHardwareID","repfin", "amendment"]

target_attributes = ["id", "swfin", "targetOSFC", "functionalDesignationSoftware", "installscriptpathname", 
                     "ata", "status","timestamp"]

sw_current = cursor.execute("SELECT %s from SOFTWARE_" % ", ".join([i + "_" for i in software_attributes]))
sw_current = sw_current.fetchall()
for sw_item in sw_current:
    current_sw_ID = sw_item[0]

    # Create Software XML Element
    sw_element = ET.SubElement(root, "Software")
    # Set Software attributes
    for s in range(1, len(software_attributes)):
        sw_element.set(software_attributes[s], str(sw_item[s]))

    # Get all Target IDs for current Software Element
    current_tg_IDs = cursor.execute("SELECT TARGET2 from SOFTWARE_TARGET_ WHERE SOFTWARE1=?", (current_sw_ID,))
    current_tg_IDs = list(chain.from_iterable(current_tg_IDs.fetchall()))
    while len(current_tg_IDs) > 0:
        tg_id = current_tg_IDs.pop(0)
        tg_current = cursor.execute("SELECT %s from TARGET_ WHERE id_=?" % ", ".join([i + "_" for i in target_attributes]), (str(tg_id).strip('[]'),))
        tg_current = tg_current.fetchall()

        for tg_item in tg_current:
            # Create Target XML Element
            tg_element = ET.SubElement(sw_element, "TargetModule")
            # Set Target attributes
            for t in range(1, len(target_attributes)):
                tg_element.set(target_attributes[t], str(tg_item[t]))

注意:在我最后的尝试中,我没有像本问题中最初假设的那样使用字典方法——我的最终方法对我的目的更有效。有关使用字典的方法的示例,请参阅此问题的选定答案。

在创建Target元素(这里的问题中没有给出代码)时,请确保将它们作为第一个参数附加到的sw_node传递给它。在

即:

target_el = SubElement(sw_node, "Target")

而不是。。。在

^{pr2}$

这种类型的代码的典型模式可能具有以下外观(大致上;需要一些测试,使用pyformatparamstyle为DB-API驱动程序编写,并且不能与其他模式一起工作):

cursor = db.cursor()
cursor.execute("SELECT * from SOFTWARE_")
for sw_item in cursor.fetchall():
  sw_el = SubElement(root_el, 'Software') ## STORING THE ELEMENT HERE
  sw_id = None
  for idx in range(len(cursor.description)):
    name = cursor.description[idx][0]
    if name == 'id':
      sw_id = sw_item[idx]
    sw_el.attrib[name] = sw_item[idx]
  ## QUERYING FOR CHILDREN HERE
  cursor.execute("SELECT TARGET_.*
                  FROM TARGET_, SOFTWARE_TARGET_
                  WHERE SOFTWARE_TARGET_.SOFTWARE1=%(sw_id)s
                    AND SOFTWARE_TARGET_.TARGET2=TARGET_.ID",
      sw_id=sw_id)
  for target_item in cursor.fetchall():
    # create a new target element
    target_el = SubElement(sw_el, 'Target')
    # assign attributes to that element
    for idx in range(len(cursor.description)):
      name = cursor.description[idx][0].rsplit('.', 1)[-1]
      target_el.attrib[name] = target_item[idx]

相关问题 更多 >