使用lxml从父级删除xml子级

时间:2017-05-08 23:27:15

标签: python xml lxml

我正在使用lxml来修改xml。在下面的代码中,我想删除所有"标题"的子项。元素并将子文本分配给其父文件。

最初

<heading><whateverchildvalue>TEXTIWANT</whateverchildvalue></heading> 

<heading>TEXTIWANT</heading>) 

我尝试使用循环,但是当我调用node.remove(attr_children [0])时,它跳出循环并继续下一次调用&#34; ET.tostring(已解析)& #34; (?)并没有修改第二个&#34;标题&#34;。要理解这一点,请删除&#34; node.remove(attr_children [0])&#34;并重新运行以下代码并比较之前打印的版本。我在这里做错了什么,以便它可以做一个适当的循环,并将子文本分配给&#34;标题&#34;所有人的父母&#34;标题&#34; xml字符串中的元素?

xml_string="""
<note>
<to>Tove</to>
<mybigheader>
    <heading><deleteme>Jani</deleteme></heading>
    <heading><wantkey>Reminder</wantkey></heading>
</mybigheader>
<body>Don't forget me this weekend!</body>
</note>
"""


def modif_xml(xml_string):

    parsed = ET.fromstring(xml_string)
    for node in parsed.iter():
        print "node is ", node
        if "heading" in node.tag:
             attr_children =  node.getchildren()
             for i in attr_children:
                 child_tag = i.tag
                 child_value = i.text
             node.remove(attr_children[0])
             node.text = child_value

    my_xml = ET.tostring(parsed)
    root = ET.XML(my_xml)
    print ET.tostring(root, pretty_print=True)


modif_xml(xml_string)

1 个答案:

答案 0 :(得分:1)

考虑http://prntscr.com/f5o8fc,这是用于转换XML文件的特殊用途声明性语言。 Python的lxml模块可以运行XSLT 1.0脚本。虽然这看起来有些过分,但您可以避免任何for循环和if逻辑。此外,XSLT脚本 XML文件,可以像任何XML一样处理:从字符串或文件解析。

特别是在下面运行XSLT(按原样复制文档),然后通过调用apply-templates而不是xsl:copy重新编写标题子项的模板(这样可以避免当前节点):

import lxml.etree as et

xml_string="""
<note>
<to>Tove</to>
<mybigheader>
    <heading><deleteme>Jani</deleteme></heading>
    <heading><wantkey>Reminder</wantkey></heading>
</mybigheader>
<body>Don't forget me this weekend!</body>
</note>
"""    
dom = et.fromstring(xml_string)

xsl_string='''
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" method="xml"/>
<xsl:strip-space elements="*"/>

  <!-- Identity Transform -->
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>  

  <xsl:template match="heading/*">
     <xsl:apply-templates />
  </xsl:template>

</xsl:transform>
'''    
xslt = et.fromstring(xsl_string)

transform = et.XSLT(xslt)
newdom = transform(dom)

print(newdom)

# <?xml version="1.0"?>
# <note>
#   <to>Tove</to>
#   <mybigheader>
#     <heading>Jani</heading>
#     <heading>Reminder</heading>
#   </mybigheader>
#   <body>Don't forget me this weekend!</body>
# </note>