【问题标题】:deleting xml child from a parent with lxml [duplicate]使用lxml从父级删除xml子级[重复]
【发布时间】:2017-05-08 23:27:14
【问题描述】:

我正在使用 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)

【问题讨论】:

    标签: python xml lxml


    【解决方案1】:

    考虑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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-16
      • 1970-01-01
      • 1970-01-01
      • 2022-10-18
      相关资源
      最近更新 更多