Python 如果具有相同的父元素,则合并具有相同标记的所有元素
我正在使用以下示例xml树:Python 如果具有相同的父元素,则合并具有相同标记的所有元素,python,xml,python-3.x,elementtree,Python,Xml,Python 3.x,Elementtree,我正在使用以下示例xml树: <group> <group_info> <Text> Text_1 </Text> </group_info> <group_info> <Text> Text_2 </Text> </group_info> <group_info>
<group>
<group_info>
<Text>
Text_1
</Text>
</group_info>
<group_info>
<Text>
Text_2
</Text>
</group_info>
<group_info>
<Text>
Text_3
</Text>
</group_info>
</group>
我的想法是循环我的所有组,将
中的所有文本信息收集到一个字符串中,然后删除树中的所有这些元素,并用信息附加一个新元素。这可能不是最好的方法,但我相对来说是新的。但是,我的输出如下所示:
<group>
<group_info>
<Text>
Text_1
</Text>
</group_info>
<group_info>
<Text>
Text_2
</Text>
</group_info>
<group_info>
<Text>
Text_3
</Text>
</group_info>
<group_info><Text>Text1 Text2 Text3</Text></group_info></group>
正文1
文本2
文本3
文本1文本2文本3
从技术上讲,最后一行是我需要的(虽然它看起来并不漂亮),但我不知道为什么它不删除其他不需要的
,即使我调用elem.remove(child)
因为没有人出来回答,所以我花了一些时间,但是如果其他人遇到同样的问题,我有答案和建议
我从您在问题中看到的初始代码开始,它不会删除旧元素,并留下非常难看的最后一行
注意:MY_XML=XML.etree.ElementTree.parse({PATH_OF_XML})
group_list = MY_XML.findall(".//group") # I do this because the actual xml is bigger with several groups
text_list = []
for group in group_list:
string_text = ""
for child in group :
for super_child in child:
if(super_child.text is not None): #Just in case None value because I cannot use string addition
string_text = string_text + super_child.text + " "
text_list.append(string_text) #I stored all the info in 1 group as a value in this list because like I stated my overall xml might be bigger with more than 1 group
for group in group_list:
for elem in group.findall(".//group_info"):
#loop over all possible <group> and removes all <group_info> inside
group.remove(elem)
#And finally to append the information gathered:
for group in group_list:
Text_elem = ET.Element("Text")
Text_elem.text = text_list[group_list.index(group)]
group_info_elem = ET.Element("Kundenhinweis_redigiert")
group_info_elem.append(Text_elem)
group.append(Kund_elem)
要调用该函数,请执行以下操作:
root = MY_XML.getroot()
pretty_xml = prettify(root)
#Next line is optional, but sometimes your string contains empty lines or lines with white spaces and/or breaklines
pretty_xml = "\n".join([s for s in pretty_xml.split("\n") if not s.isspace()])
print(pretty_xml)
输出将是:
<group>
<group_info>
<Text>Text1 Text2 Text3</Text>
</group_info>
</group>
文本1文本2文本3
希望这能帮助其他新来者。因为没有人站出来回答,我花了一些时间,但如果其他人遇到同样的问题,我有答案和建议 我从您在问题中看到的初始代码开始,它不会删除旧元素,并留下非常难看的最后一行 注意:
MY_XML=XML.etree.ElementTree.parse({PATH_OF_XML})
group_list = MY_XML.findall(".//group") # I do this because the actual xml is bigger with several groups
text_list = []
for group in group_list:
string_text = ""
for child in group :
for super_child in child:
if(super_child.text is not None): #Just in case None value because I cannot use string addition
string_text = string_text + super_child.text + " "
text_list.append(string_text) #I stored all the info in 1 group as a value in this list because like I stated my overall xml might be bigger with more than 1 group
for group in group_list:
for elem in group.findall(".//group_info"):
#loop over all possible <group> and removes all <group_info> inside
group.remove(elem)
#And finally to append the information gathered:
for group in group_list:
Text_elem = ET.Element("Text")
Text_elem.text = text_list[group_list.index(group)]
group_info_elem = ET.Element("Kundenhinweis_redigiert")
group_info_elem.append(Text_elem)
group.append(Kund_elem)
要调用该函数,请执行以下操作:
root = MY_XML.getroot()
pretty_xml = prettify(root)
#Next line is optional, but sometimes your string contains empty lines or lines with white spaces and/or breaklines
pretty_xml = "\n".join([s for s in pretty_xml.split("\n") if not s.isspace()])
print(pretty_xml)
输出将是:
<group>
<group_info>
<Text>Text1 Text2 Text3</Text>
</group_info>
</group>
文本1文本2文本3
希望这对其他新手有所帮助。考虑一下,这是一种专门用于转换XML文件的专用语言,您可以通过索引相同的节点名称并对其文本值进行分组来运行。虽然Python的内置xml.ElementTree
不支持XSLT,但其第三方模块lxml
支持XSLT1.0脚本。您可以在不使用单个for
循环或手动美化输出的情况下完成此操作
XSLT(另存为.xsl文件,一个特殊的.xml文件)
考虑一下,设计用于转换XML文件的专用语言,您可以通过索引相同的节点名称并将其文本值分组来运行。虽然Python的内置xml.ElementTree
不支持XSLT,但其第三方模块lxml
支持XSLT1.0脚本。您可以在不使用单个for
循环或手动美化输出的情况下完成此操作
XSLT(另存为.xsl文件,一个特殊的.xml文件)
我在搜索中读到过,问题是我在公司的计算机上工作,不允许安装额外的python模块。我仅有的两个是
xml.etree.ElementTree
和xml.dom.minidom
导入“lxml”时,我得到了一个ImportError。哦,我多么希望。我无法控制xml输入,因为我从另一个部门接收xml输入,并且必须在python中执行更改。XSLT是一种行业语言,可以与或其他语言一起运行。请参阅安装程序,具体取决于您使用的是PC还是Unix,Python可以通过子流程在命令行中调用它。我将对此进行研究,一旦任务变得更困难,它可能会很有用。谢谢。我在搜索中读到过,问题是我在公司的计算机上工作,不允许安装额外的python模块。我仅有的两个是xml.etree.ElementTree
和xml.dom.minidom
导入“lxml”时,我得到了一个ImportError。哦,我多么希望。我无法控制xml输入,因为我从另一个部门接收xml输入,并且必须在python中执行更改。XSLT是一种行业语言,可以与或其他语言一起运行。请参阅安装程序,具体取决于您使用的是PC还是Unix,Python可以通过子流程在命令行中调用它。我将对此进行研究,一旦任务变得更困难,它可能会很有用。非常感谢。
<group>
<group_info>
<Text>Text1 Text2 Text3</Text>
</group_info>
</group>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>
<xsl:key name="group_key" match="group/*" use="name()" />
<xsl:template match="/group">
<xsl:copy>
<xsl:apply-templates select="*[generate-id() =
generate-id(key('group_key', name())[1])]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="group/*">
<xsl:copy>
<xsl:element name="{name(*)}">
<xsl:for-each select="key('group_key', name())">
<xsl:value-of select="normalize-space(*)"/>
<xsl:if test="position() != last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
import lxml.etree as et
# LOAD XML AND XSL
doc = et.parse('/path/to/Input.xml')
xsl = et.parse('/path/to/XSLT_Script.xsl')
# CONFIGURE TRANSFORMER
transform = et.XSLT(xsl)
# RUN TRANSFORMATION
result = transform(doc)
# PRINT RESULT
print(result)
# SAVE TO FILE
with open('/path/to/Output.xml', 'wb') as f:
f.write(result)