python - how to write empty tree node as empty string to xml file

后端 未结 3 1257
花落未央
花落未央 2021-01-27 01:25

I want to remove elements of a certain tag value and then write out the .xml file WITHOUT any tags for those deleted elements; is my only option to create a new tre

3条回答
  •  情深已故
    2021-01-27 02:02

    import lxml.etree as et
    
    xml  = et.parse("test.xml")
    
    for node in xml.xpath("//neighbor"):
        node.getparent().remove(node)
    
    
    xml.write("out.xml",encoding="utf-8",xml_declaration=True)
    

    Using elementTree, we need to find the parents of the neighbor nodes then find the neighbor nodes inside that parent and remove them:

    from xml.etree import ElementTree as et
    
    xml  = et.parse("test.xml")
    
    
    for parent in xml.getroot().findall(".//neighbor/.."):
          for child in parent.findall("./neighbor"):
              parent.remove(child)
    
    
    xml.write("out.xml",encoding="utf-8",xml_declaration=True)
    

    Both will give you:

    
    
        
            1
            2008
            141100
            
        
            4
            2011
            59900
            
        
            68
            2011
            13600
            
    
    

    Using your attribute logic and modifying the xml a bit like below:

    x = """
    
        
            1
            2008
            141100
            
            
        
        
            4
            2011
            59900
               
            
        
        
            68
            2011
            13600
            
            
        
    """
    

    Using lxml:

    import lxml.etree as et
    
    xml = et.fromstring(x)
    
    for node in xml.xpath("//neighbor[not(@make) and not(@job) and not(@make)]"):
        node.getparent().remove(node)
    print(et.tostring(xml))
    

    Would give you:

     
        
            1
            2008
            141100
            
        
            4
            2011
            59900
            
            
        
            68
            2011
            13600
            
            
    
    

    The same logic in ElementTree:

    from xml.etree import ElementTree as et
    
    xml = et.parse("test.xml").getroot()
    
    atts = {"build", "job", "make"}
    
    for parent in xml.findall(".//neighbor/.."):
        for child in parent.findall(".//neighbor")[:]:
            if not atts.issubset(child.attrib):
                parent.remove(child)
    

    If you are using iter:

    from xml.etree import ElementTree as et
    
    xml = et.parse("test.xml")
    
    for parent in xml.getroot().iter("*"):
        parent[:] = (child for child in parent if child.tag != "neighbor")
    

    You can see we get the exact same output:

    In [30]: !cat /home/padraic/untitled6/test.xml
    
    
        #
          
            1
            
            2008
          
            141100
            
            
        
        
            4
            2011
            59900
            
        
        
            68
            2011
            13600
            
            
        
    
    In [31]: paste
    def test():
        import lxml.etree as et
        xml = et.parse("/home/padraic/untitled6/test.xml")
        for node in xml.xpath("//neighbor"):
            node.getparent().remove(node)
        a = et.tostring(xml)
        from xml.etree import ElementTree as et
        xml = et.parse("/home/padraic/untitled6/test.xml")
        for parent in xml.getroot().iter("*"):
            parent[:] = (child for child in parent if child.tag != "neighbor")
        b = et.tostring(xml.getroot())
        assert  a == b
    
    ## -- End pasted text --
    
    In [32]: test()
    

提交回复
热议问题