lxml non-recursive full tag
<p>Given the following xml:</p>

<pre><code>&lt;node a='1' b='1'&gt;
   &lt;subnode x='25'/&gt;
&lt;/node&gt;
</code></pre>

<p>I would like to extract the tagname and all attributes for the first node, i.e., the verbatim code:</p>

<pre><code>&lt;node a='1' b='1'&gt;
</code></pre>

<p>without the subnode.</p>

<p>For example in Python, <code>tostring</code> returns too much:</p>

<pre><code>from lxml import etree
root = etree.fromstring("&lt;node a='1' b='1'&gt;&lt;subnode x='25'&gt;some text&lt;/subnode&gt;&lt;/node&gt;")
print(etree.tostring(root))
</code></pre>

<p>returns</p>

<pre><code>b'&lt;node a="1" b="1"&gt;&lt;subnode x="25"&gt;some text&lt;/subnode&gt;&lt;/node&gt;'
</code></pre>

<p>The following gives the desired result, but is much too verbose:</p>

<pre><code>tag = root.tag
for att, val in root.attrib.items():
    tag += ' '+att+'="'+val+'"'
tag = '&lt;'+tag+'&gt;'
print(tag)
</code></pre>

<p>result:</p>

<pre><code>&lt;node a="1" b="1"&gt;
</code></pre>

<p>What is an easier (and guaranteed attribute order preserving) way of doing this?</p>

<p>You can remove all of the subnodes.</p>

<pre><code>from lxml import etree

root = etree.fromstring("&lt;node a='1' b='1'&gt;&lt;subnode x='25'&gt;some text&lt;/subnode&gt;&lt;/node&gt;")
for subnode in root.xpath("//subnode"):
    subnode.getparent().remove(subnode)

etree.tostring(root)  # '&lt;node a="1" b="1"/&gt;'
</code></pre>

<p>Alternatively, you can use a simple regex. Order is guaranteed.</p>

<pre><code>import re
res = re.search('&lt;(.*?)&gt;', etree.tostring(root))
res.group(1)  # "node a='1' b='1'"
</code></pre>

python recursion lxml