python - 使用 lxml 从父项中删除 xml 子项

标签 python xml lxml

<分区>

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

最初

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

<heading>TEXTIWANT</heading>) 

我尝试为此使用循环,但是不知何故,当我调用 node.remove(attr_children[0]) 时,它会跳出循环并继续下一次调用“ET.tostring(parsed)”(?)并没有修改第二个“标题”。要理解这一点,请删除“node.remove(attr_children[0])”并重新运行以下代码并比较之前打印的版本。我在这里做错了什么,以便它可以执行正确的循环,并将子文本分配给 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)

最佳答案

考虑 XSLT ,用于转换 XML 文件的专用声明性语言。 Python 的 lxml 模块可以运行 XSLT 1.0 脚本。虽然这看起来有点矫枉过正,但您可以避免任何 for 循环和 if 逻辑。此外,XSLT 脚本 XML 文件,可以像处理任何 XML 一样处理:从字符串或文件中解析。

特别是在下面运行 Identity Transform (按原样复制文档),然后通过调用 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>

关于python - 使用 lxml 从父项中删除 xml 子项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43858717/

相关文章:

python - 如何生成一个列表以将值流式传输到 flask ?

用于 RSS 提要解析的 Objective-C 库?

python - 尝试制作网络爬虫来解析网站链接时接收和空列表

python - 如何在 LXML 中使用 XPATH 根据属性指定特定元素

Python 代码在 Eclipse 中出错,但在终端中运行良好

python - 用括号替换正则表达式

android - 解析 XML : prefix must not be bound to one of the reserved namespace names 时出错

XML 架构 : Referenced attribute is missing

python - lxml xsi :schemaLocation namespace URI validation issue

python - LPTHW :Ex48 Unit test(using nosetests), 类、方法参数类型错误