0

How to comment an entire specific block and a particular tag of xml in python ? In below xml, there are many <list> tags. 1) Have to comment entire block <list> {some_data}</list>, where <list name="list_name1"> 2) If you observe <list name="list_name3"> , there are 2 <p> tags in a <item>.

<p name="address1">some/address-3</p><p name="address1_1">some/address-1_1</p>

Here, have to comment second <p> tag, ie.,<p name="address1_1">some/address-1_1</p>, all such instances.

How can we achieve this in python ?
Which is best xml module in python ?

sample_file.xml

    <raml xmlns="abcd.xsd" version="0.1">
    <newData type="hw">
        <header>
          <log action="create" dateTime="2020-01-15T16:45:12.001Z" />
        </header>
        <sampleObject class="com.abcd.efgh:VASDF" distName="some_unique_name" operation="update" version="HDGEKB_8363_845"> 
            <p name="p_name1">true</p>
            <list name="list_name1">
                <item>
                    <p name="address1">some/address-1</p>
                    <p name="value">some/value-1</p>
                </item>
                <item>
                    <p name="address1">some/address-2</p>
                    <p name="value">some/value-2</p>
                </item>
                <item>
                    <p name="address1">some/address-3</p>
                    <p name="value">some/value-3</p>
                </item>
                <item>
                    <p name="address1">some/address-4</p>
                    <p name="value">some/value-4</p>
                </item>
                <item>
                    <p name="address1">some/address-5</p>
                    <p name="value">some/value-5</p>
                </item>
                <item>
                    <p name="address1">some/address-6</p>
                    <p name="value">some/value-6</p>
                </item>
            </list>
            <list name="list_name2">
                <item>
                    <p name="address1">some/address-1</p>
                    <p name="value">1</p>
                </item>
                <item>
                    <p name="address1">some/address-2</p>
                    <p name="value">2</p>
                </item>
                <item>
                    <p name="address1">some/address-3</p>
                    <p name="value">3</p>
                </item>
                <item>
                    <p name="address1">some/address-4</p>
                    <p name="value">4</p>
                </item>
                <item>
                    <p name="address1">some/address-5</p>
                    <p name="value">5</p>
                </item>
                <item>
                    <p name="address1">some/address-6</p>
                    <p name="value">6</p>
                </item>
            </list>
            <list name="list_name3">
                <item>
                    <p name="address1">some/address-1</p>
                    <p name="address1_1">some/address-1_1</p>
                    <p name="value">1</p>
                </item>
                <item>
                    <p name="address1_1">some/address-1_1</p>
                    <p name="value">1_1</p>
                <item>
                <item>
                    <p name="address1">some/address-2</p>
                    <p name="value">2</p>
                </item>
                <item>
                    <p name="address1">some/address-3</p>
                    <p name="address1_1">some/address-1_1</p>
                    <p name="value">3</p>
                </item>
                <item>
                    <p name="address1_1">some/address-1_1</p>
                    <p name="value">3_3</p>
                <item>
                <item>
                    <p name="address1">some/address-4</p>
                    <p name="value">4</p>
                </item>
                <item>
                    <p name="address1">some/address-5</p>
                    <p name="value">5</p>
                </item>
                <item>
                    <p name="address1">some/address-6</p>
                    <p name="value">6</p>
                </item>
             </list>                                                                
        </sampleObject> 
    </newData>

</raml>

output_file.xml , should look like below

<raml xmlns="abcd.xsd" version="0.1">
    <newData type="hw">
        <header>
          <log action="create" dateTime="2020-01-15T16:45:12.001Z" />
        </header>
        <sampleObject class="com.abcd.efgh:VASDF" distName="some_unique_name" operation="update" version="HDGEKB_8363_845"> 
            <p name="p_name1">true</p>
            <!--<list name="list_name1">
                <item>
                    <p name="address1">some/address-1</p>
                    <p name="value">some/value-1</p>
                </item>
                <item>
                    <p name="address1">some/address-2</p>
                    <p name="value">some/value-2</p>
                </item>
                <item>
                    <p name="address1">some/address-3</p>
                    <p name="value">some/value-3</p>
                </item>
                <item>
                    <p name="address1">some/address-4</p>
                    <p name="value">some/value-4</p>
                </item>
                <item>
                    <p name="address1">some/address-5</p>
                    <p name="value">some/value-5</p>
                </item>
                <item>
                    <p name="address1">some/address-6</p>
                    <p name="value">some/value-6</p>
                </item>
            </list> -->
            <list name="list_name2">
                <item>
                    <p name="address1">some/address-1</p>
                    <p name="value">1</p>
                </item>
                <item>
                    <p name="address1">some/address-2</p>
                    <p name="value">2</p>
                </item>
                <item>
                    <p name="address1">some/address-3</p>
                    <p name="value">3</p>
                </item>
                <item>
                    <p name="address1">some/address-4</p>
                    <p name="value">4</p>
                </item>
                <item>
                    <p name="address1">some/address-5</p>
                    <p name="value">5</p>
                </item>
                <item>
                    <p name="address1">some/address-6</p>
                    <p name="value">6</p>
                </item>
            </list>
            <list name="list_name3">
                <item>
                    <p name="address1">some/address-1</p>
                    <!--<p name="address1_1">some/address-1_1</p>-->
                    <p name="value">1</p>
                </item>
                <item>
                    <p name="address1_1">some/address-1_1</p>
                    <p name="value">1_1</p>
                <item>
                <item>
                    <p name="address1">some/address-2</p>
                    <p name="value">2</p>
                </item>
                <item>
                    <p name="address1">some/address-3</p>
                    <!--<p name="address1_1">some/address-1_1</p>-->
                    <p name="value">3</p>
                </item>
                <item>
                    <p name="address1_1">some/address-1_1</p>
                    <p name="value">3_3</p>
                <item>
                <item>
                    <p name="address1">some/address-4</p>
                    <p name="value">4</p>
                </item>
                <item>
                    <p name="address1">some/address-5</p>
                    <p name="value">5</p>
                </item>
                <item>
                    <p name="address1">some/address-6</p>
                    <p name="value">6</p>
                </item>
             </list>                                                                
        </sampleObject> 
    </newData>

</raml>
3
  • Perhaps this helps: stackoverflow.com/q/44416111/407651 Commented Apr 8, 2020 at 5:33
  • 1
    "Which is best xml module in python?" If by "best" you mean "has the most features", then my answer would be lxml. Commented Apr 8, 2020 at 6:11
  • Thanks @mzjn , How can we comment that entire block ? and block tag containing only address1_1, where both address1 and address1_1 (not where alone address1_1 present. Refer section <list name="list_name3">). Can you help me ? Commented Apr 8, 2020 at 6:25

1 Answer 1

2

lxml is able to replace any element with another element, including comment, but unfortunately if you create the text of this comment from an existing element, lxml copies the default namespace again to the comment text.

So instead of lxml I decided to use BeautifulSoup, which treats namespaces more "leniently".

Try the below code:

from bs4 import BeautifulSoup, Comment

soup = BeautifulSoup(open('Input.xml'), 'xml')
for elem in soup.findAll('list'):
    elem.replace_with(Comment(str(elem)))
print(soup.prettify())

For your input XML, shortened a bit, I got:

<?xml version="1.0" encoding="utf-8"?>
<raml version="0.1" xmlns="abcd.xsd">
  <newData type="hw">
    <header>
      <log action="create" dateTime="2020-01-15T16:45:12.001Z"/>
    </header>
    <sampleObject class="com.abcd.efgh:VASDF" distName="some_unique_name" operation="update" version="HDGEKB_8363_845">
      <p name="p_name1">true</p>
<!--<list name="list_name1">
<item>
<p name="address1">some/address-1</p>
<p name="value">1</p>
</item>
<item>
<p name="address1">some/address-2</p>
<p name="value">2</p>
</item>
</list>-->
<!--<list name="list_name2">
<item>
<p name="address1">some/address-3</p>
<p name="value">3</p>
</item>
<item>
<p name="address1">some/address-4</p>
<p name="value">4</p>
</item>
</list>-->
    </sampleObject>
  </newData>
</raml>

Edit

If you want to comment out only one list element (e.g. with name attribute set to 'list_name1'), the correction is simple:

findAll has another parameter, namely attrs (a dictionary), where you can pass any attribute names / values to narrow down the selection.

In this case change the loop to:

for elem in soup.findAll('list', attrs={'name': 'list_name1'}):
    elem.replace_with(Comment(str(elem)))

To only delete selected elements, the name of a method to do it is less intuitive, namely it is decompose.

To do it, run:

for elem in soup.findAll('list', attrs={'name': 'list_name1'}):
    elem.decompose()

Edit following the comment about XML prefix

One recipe to remove XML prefix is to call BeautifulSoup without the second xml argument.

But then the root element in the output is html, containing inside body element and raml element is inside it.

So to drop these 2 "outer" elements, change the code to:

soup = BeautifulSoup(open('Input.xml'))
for elem in soup.findAll('list'):
    elem.replace_with(Comment(str(elem)))
print(soup.html.body.raml.prettify())

Also e.g. <p> element is kept in a single line.

A bit "dirty" solution, but hopefully leading to the expected result.

Sign up to request clarification or add additional context in comments.

16 Comments

Thank you. How to comment only list-block where name="list_name1" ?
And also, can we delete the same ? like, delete only <list> where name="list_name1"
elem.replace_with(Comment(str(elem))) , not commenting in file. Instead, it's printing that entire block.
elem.decompose() , not deleting that entire block
Note that findAll in the last example contains attrs={'name': 'list_name1'} parameter, so only this one instance of list is deleted. If you drop attrs parameter, then all list elements will be deleted. Try on your own computer.
|

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.