Search code examples
pythonxmlantxml-parsingminidom

Commenting and uncommenting XML via Python


I would like to know of a way to comment and uncomment an element in XML using Python.

<target depends="create-build-dir" name="build-Folio">
   <property name="project.name" value="Folio"/>
   <ant antfile="build.xml" dir="Folio/FolioUI" inheritall="false" target="package"/>
   <ant antfile="build.xml" dir="Folio/Folio" inheritall="false" target="package"/>
</target>

How can I get it to look like this:

<target depends="create-build-dir" name="build-Folio">
   <property name="project.name" value="Folio"/>
   <ant antfile="build.xml" dir="Folio/FolioUI" inheritall="false" target="deploy"/>
   <!-- <ant antfile="build.xml" dir="Folio/Folio" inheritall="false" target="deploy"/> -->
</target>

and then remove the comments again as needed... or

I am using minidom from xml.dom. Do I need to use a different XML parser? Would prefer to avoid using regex... that would be a nightmare.


Solution

  • The script below uses xml.dom.minidom and includes functions for both commenting and uncommenting nodes:

    from xml.dom import minidom
    
    xml = """\
    <target depends="create-build-dir" name="build-Folio">
       <property name="project.name" value="Folio"/>
       <ant antfile="build.xml" dir="Folio/FolioUI" inheritall="false" target="package"/>
       <ant antfile="build.xml" dir="Folio/Folio" inheritall="false" target="package"/>
    </target>
    """
    
    def comment_node(node):
        comment = node.ownerDocument.createComment(node.toxml())
        node.parentNode.replaceChild(comment, node)
        return comment
    
    def uncomment_node(comment):
        node = minidom.parseString(comment.data).firstChild
        comment.parentNode.replaceChild(node, comment)
        return node
    
    doc = minidom.parseString(xml).documentElement
    
    comment_node(doc.getElementsByTagName('ant')[-1])
    
    xml = doc.toxml()
    
    print 'comment_node():\n'
    print xml
    print
    
    doc = minidom.parseString(xml).documentElement
    
    comment = doc.lastChild.previousSibling
    
    print 're-parsed comment:\n'
    print comment.toxml()
    print
    
    uncomment_node(comment)
    
    print 'uncomment_node():\n'
    print doc.toxml()
    print
    

    Output:

    comment_node():
    
    <target depends="create-build-dir" name="build-Folio">
       <property name="project.name" value="Folio"/>
       <ant antfile="build.xml" dir="Folio/FolioUI" inheritall="false" target="package"/>
       <!--<ant antfile="build.xml" dir="Folio/Folio" inheritall="false" target="package"/>-->
    </target>
    
    re-parsed comment:
    
    <!--<ant antfile="build.xml" dir="Folio/Folio" inheritall="false" target="package"/>-->
    
    uncomment_node():
    
    <target depends="create-build-dir" name="build-Folio">
       <property name="project.name" value="Folio"/>
       <ant antfile="build.xml" dir="Folio/FolioUI" inheritall="false" target="package"/>
       <ant antfile="build.xml" dir="Folio/Folio" inheritall="false" target="package"/>
    </target>