4

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.

2
  • How should one specify what to comment (line number, x+y position)? Commented Jan 6, 2012 at 21:31
  • hopefully by attribute if its possible Commented Jan 6, 2012 at 21:44

3 Answers 3

5

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>
Sign up to request clarification or add additional context in comments.

5 Comments

Does this work with existing comments? Say we serialize this out to a file. Come back open the file parse it then remove the comment... Would this example work, it appears that it still requires that the tree still exists...
@MichaelBallent. Yes, it works if the xml is re-parsed. I've updated my example script and output to clarify that.
Accepting this answer since it lets me to continue to use minidom. Thank you very much.
What if my comment is <!--ant antfile="build.xml" dir="Folio/Folio" inheritall="false" target="package"></ant--> instead of <!--<ant antfile="build.xml" dir="Folio/Folio" inheritall="false" target="package"/>-->
@Ridhuvarshan. That makes no sense. If you uncomment that, it will result in invalid xml. This question is about commenting and uncommenting xml tags/nodes, not arbitrary strings.
2
a='''<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>
         '''
import xml.etree.ElementTree as ET
from xml.etree.ElementTree import Comment, tostring

root = ET.fromstring(a)
element = root.getchildren()[2]
comment_element = Comment(tostring(element))
root.insert(2, comment_element)
root.remove(element)
print tostring(root)

Comments

-1

With ElementTree:

from xml.etree import ElementTree as etree

import sys

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>
"""

doc = etree.fromstring(xml)

antfiles = doc.getiterator("ant")
antfiles[1].tag = "!--"          # Comment the second antfile

print etree.tostring(doc)

# >>>
# <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" />
#    <!-- antfile="build.xml" dir="Folio/Folio" inheritall="false" target="package" />
# </target>

###

1 Comment

@mzjn: you're right, then I would use et.Comment like user... did it in the other answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.