Python 和 ElementTree:如何将 elements/subelements 嵌套在 XML 中?
Python and ElementTree: How can I nest elements/subelements in an XML?
背景
我正在使用 Python 2.6、ElementTree 和 SQLite3。我的脚本目前执行以下操作:
- 连接到数据库以从 tables/schema
检索信息
- 向 XML 树添加必要的数据
- 输出一个(目前不正确的)XML文件
代码
以下是我如何检索模式数据并将元素添加到 XML。我使用 SOFTWARE_
和 TARGET_
table 来执行此操作。这是 SOFTWARE_
table:
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_
table:
target_attributes = ["id", "functionalDesignationSoftware", "installscriptpathname", "ata", "status",
"swfin", "targetOSFC", "timestamp"]
target = db.cursor().execute("SELECT %s from TARGET_" % ", ".join([i + "_" for i in target_attributes]))
target_Data = target.fetchall()
ID2 = db.cursor().execute("SELECT id_ from TARGET_")
target_IDs = ID2.fetchall()
## CURRENTLY INCORRECT - only adds to the last created Software Element ##
for tg in target_Data:
tg_node = ET.SubElement(sw_node, "TargetModule")
for t in range(1, len(target_attributes)):
tg_node.set(target_attributes[t], str(tg[t]))
这就是我存储来自 table 的信息的方式,其唯一目的是连接来自 other table 的数据。 SOFTWARE_TARGET_
table 将 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_
table 的信息确定。我找到了如何遍历我的字典,像这样:
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)
问题
如何根据数据库 table 中的信息创建格式正确的 XML 文件(如 Attemps 部分所述)秒?我创建了字典,认为我可以将它用于此目的 - 如果有必要,请告诉我。
备注
This 是我根据 SOFTWARE_TARGET_
table 创建的字典的样子。键表示来自 SOFTWARE_
的 id_
模式,值表示来自 TARGET_
的 id_
模式。 (如果我的术语听起来不对,请告诉我 - 数据库有时会让我感到困惑)。
创建 Target
元素时(此处问题中未给出代码),请确保将要附加的 sw_node
作为第一个参数传递。
即:
target_el = SubElement(sw_node, "Target")
而不是...
target_el = SubElement(root_node, "Target")
此类代码的典型模式可能具有以下外观(大致;需要一些测试,使用 pyformat
paramstyle 为 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]
哎呀,差点忘了 - 这是我在完成的 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]))
注意: 在我上面的最后一次尝试中,我并没有像最初在这个问题中假设的那样最终使用字典方法——我的最终方法对我的目的来说更有效。有关使用字典的方法示例,请参阅此问题的选定答案。
背景
我正在使用 Python 2.6、ElementTree 和 SQLite3。我的脚本目前执行以下操作:
- 连接到数据库以从 tables/schema 检索信息
- 向 XML 树添加必要的数据
- 输出一个(目前不正确的)XML文件
代码
以下是我如何检索模式数据并将元素添加到 XML。我使用 SOFTWARE_
和 TARGET_
table 来执行此操作。这是 SOFTWARE_
table:
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_
table:
target_attributes = ["id", "functionalDesignationSoftware", "installscriptpathname", "ata", "status",
"swfin", "targetOSFC", "timestamp"]
target = db.cursor().execute("SELECT %s from TARGET_" % ", ".join([i + "_" for i in target_attributes]))
target_Data = target.fetchall()
ID2 = db.cursor().execute("SELECT id_ from TARGET_")
target_IDs = ID2.fetchall()
## CURRENTLY INCORRECT - only adds to the last created Software Element ##
for tg in target_Data:
tg_node = ET.SubElement(sw_node, "TargetModule")
for t in range(1, len(target_attributes)):
tg_node.set(target_attributes[t], str(tg[t]))
这就是我存储来自 table 的信息的方式,其唯一目的是连接来自 other table 的数据。 SOFTWARE_TARGET_
table 将 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_
table 的信息确定。我找到了如何遍历我的字典,像这样:
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)
问题
如何根据数据库 table 中的信息创建格式正确的 XML 文件(如 Attemps 部分所述)秒?我创建了字典,认为我可以将它用于此目的 - 如果有必要,请告诉我。
备注
This 是我根据 SOFTWARE_TARGET_
table 创建的字典的样子。键表示来自 SOFTWARE_
的 id_
模式,值表示来自 TARGET_
的 id_
模式。 (如果我的术语听起来不对,请告诉我 - 数据库有时会让我感到困惑)。
创建 Target
元素时(此处问题中未给出代码),请确保将要附加的 sw_node
作为第一个参数传递。
即:
target_el = SubElement(sw_node, "Target")
而不是...
target_el = SubElement(root_node, "Target")
此类代码的典型模式可能具有以下外观(大致;需要一些测试,使用 pyformat
paramstyle 为 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]
哎呀,差点忘了 - 这是我在完成的 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]))
注意: 在我上面的最后一次尝试中,我并没有像最初在这个问题中假设的那样最终使用字典方法——我的最终方法对我的目的来说更有效。有关使用字典的方法示例,请参阅此问题的选定答案。