code: def move_siblings(
          start, end, new_,
          keep_start_boundary=False,
          keep_end_boundary=False
  ):
      
      old_ = start.getparent()
      if keep_start_boundary:
          new_.append(copy(start))
  
      else:
          if start.tail:
              # copy the existing tail as text
              new_.text = start.tail
  
      # get all siblings
      for node in start.itersiblings():
          if node is not end:
              new_.append(node)
  
          elif node is end:
              # if this is already the end boundary, then we are done
              if keep_end_boundary:
                  new_.append(copy(node))
  
              break
  
      # replace start boundary with new node
      old_.replace(start, new_)
  
      # remove ending boundary we already copied it if needed
      old_.remove(end)
docs: a helper function that will replace a start/end node pair
      by a new containing element, effectively moving all in-between siblings
      This is particularly helpful to replace for /for loops in tables
      with the content resulting from the iteration
  
      This function call returns None. The parent xml tree is modified in place
  
      @param start: the starting xml node
      @type start: lxml.etree.Element
  
      @param end: the ending xml node
      @type end: lxml.etree.Element
  
      @param new_: the new xml element that will replace the start/end pair
      @type new_: lxlm.etree.Element
  
      @param keep_start_boundary: Flag to let the function know if it copies
      your start tag to the new_ node or not, Default value is False
      @type keep_start_boundary: bool
  
      @param keep_end_boundary: Flag to let the function know if it copies
      your end tag to the new_ node or not, Default value is False
      @type keep_end_boundary: bool
  
      @returns: None