<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.doughellmann.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkAGRnc9fip7ImA9WxBbFUo.&quot;"><id>tag:blogger.com,1999:blog-5440028356946346379</id><updated>2010-03-14T10:58:47.966-04:00</updated><title>Doug Hellmann</title><subtitle type="html">&lt;p&gt;Code Interstices&lt;/p&gt;

&lt;p&gt;All the little things that happen between bouts of coding.  Covering internet technologies, Python, Mac OS X, and open source.&lt;/p&gt;</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://blog.doughellmann.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default?start-index=4&amp;max-results=3&amp;redirect=false&amp;v=2" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>371</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>3</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.doughellmann.com/DougHellmann" /><feedburner:info uri="doughellmann" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-sa/2.0/" /><logo>http://creativecommons.org/images/public/somerights20.gif</logo><feedburner:emailServiceId>DougHellmann</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;AkAGSX4-fSp7ImA9WxBbFUo.&quot;"><id>tag:blogger.com,1999:blog-5440028356946346379.post-2248271756635298269</id><published>2010-03-14T10:58:00.001-04:00</published><updated>2010-03-14T10:58:48.055-04:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-14T10:58:48.055-04:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="PyMOTW" /><title>PyMOTW: Parsing XML Documents with ElementTree</title><content type="html">&lt;div class="section" id="parsing-xml-documents-with-elementtree"&gt;&lt;span id="xml-etree-elementtree-parsing"&gt;&lt;/span&gt;&lt;h1&gt;Parsing XML Documents with ElementTree&lt;/h1&gt;&lt;p&gt;Parsed XML documents are represented in memory by ElementTree and&lt;br /&gt;Element objects connected into a tree structure based on the way the&lt;br /&gt;nodes in the XML document are nested.&lt;/p&gt;&lt;div class="section" id="parsing-an-entire-document"&gt;&lt;h2&gt;Parsing an Entire Document&lt;/h2&gt;&lt;p&gt;When you parse an entire document with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;parse()&lt;/span&gt;&lt;/tt&gt;, an ElementTree&lt;br /&gt;instance is returned.  The tree knows about all of the data in the&lt;br /&gt;input document, and the nodes of the tree can be searched or&lt;br /&gt;manipulated in place.  While this flexibility can make working with&lt;br /&gt;the parsed document a little easier, it typically takes more memory&lt;br /&gt;than an event-based parsing approach since the entire document must be&lt;br /&gt;loaded at one time.&lt;/p&gt;&lt;p&gt;The memory footprint of small, simple documents such as this list of&lt;br /&gt;podcasts represented as an &lt;a class="reference external" href="http://www.opml.org/"&gt;OPML&lt;/a&gt; outline is not significant:&lt;/p&gt;&lt;div class="highlight-xml"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nt"&gt;&amp;lt;opml&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Podcasts&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;dateCreated&amp;gt;&lt;/span&gt;Sun, 07 Mar 2010 15:53:26 GMT&lt;span class="nt"&gt;&amp;lt;/dateCreated&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;dateModified&amp;gt;&lt;/span&gt;Sun, 07 Mar 2010 15:53:26 GMT&lt;span class="nt"&gt;&amp;lt;/dateModified&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Science and Tech&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;APM: Future Tense&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.publicradio.org/columns/futuretense/podcast.xml&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.publicradio.org/columns/futuretense/&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Engines Of Our Ingenuity Podcast&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.npr.org/rss/podcast.php?id=510030&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.uh.edu/engines/engines.htm&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Science &amp;amp;#38; the City&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.nyas.org/Podcasts/Atom.axd&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.nyas.org/WhatWeDo/SciencetheCity.aspx&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;/outline&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Books and Fiction&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Podiobooker&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://feeds.feedburner.com/podiobooks&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.podiobooks.com/blog&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;The Drabblecast&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://web.me.com/normsherman/Site/Podcast/rss.xml&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://web.me.com/normsherman/Site/Podcast/Podcast.html&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tor.com / category / tordotstories&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.tor.com/rss/category/TorDotStories&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.tor.com/&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;/outline&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Computers and Programming&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;MacBreak Weekly&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://leo.am/podcasts/mbw&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://twit.tv/mbw&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;FLOSS Weekly&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://leo.am/podcasts/floss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://twit.tv&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Core Intuition&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.coreint.org/podcast.xml&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.coreint.org/&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;/outline&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Python&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;    &lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;PyCon Podcast&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://advocacy.python.org/podcasts/pycon.rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://advocacy.python.org/podcasts/&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;A Little Bit of Python&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://advocacy.python.org/podcasts/littlebit.rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://advocacy.python.org/podcasts/&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Django Dose Everything Feed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://djangodose.com/everything/feed/&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;/outline&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Miscelaneous&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;br /&gt;	&lt;span class="nt"&gt;&amp;lt;outline&lt;/span&gt; &lt;span class="na"&gt;text=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;dhellmann&amp;#39;s CastSampler Feed&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;rss&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;xmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.castsampler.com/cast/feed/rss/dhellmann/&amp;quot;&lt;/span&gt; &lt;br /&gt;             &lt;span class="na"&gt;htmlUrl=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;http://www.castsampler.com/users/dhellmann/&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;/outline&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nt"&gt;&amp;lt;/opml&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;To parse the file, pass an open file handle to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;parse()&lt;/span&gt;&lt;/tt&gt;.  It will&lt;br /&gt;read the data, parse the XML, and return an ElementTree object.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;podcasts.opml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_parse_opml.py&lt;br /&gt;&amp;lt;xml.etree.ElementTree.ElementTree instance at 0x82f58&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="traversing-the-parsed-tree"&gt;&lt;h2&gt;Traversing the Parsed Tree&lt;/h2&gt;&lt;p&gt;Now that we have a parsed XML tree, we can iterate over it, visiting&lt;br /&gt;all of the children in order and examining their attributes and&lt;br /&gt;contents.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;podcasts.opml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getiterator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Here we print the entire tree, one tag at a time.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_dump_opml.py&lt;br /&gt;opml {'version': '1.0'}&lt;br /&gt;head {}&lt;br /&gt;title {}&lt;br /&gt;dateCreated {}&lt;br /&gt;dateModified {}&lt;br /&gt;body {}&lt;br /&gt;outline {'text': 'Science and Tech'}&lt;br /&gt;outline {'xmlUrl': 'http://www.publicradio.org/columns/futuretense/podcast.xml', 'text': 'APM: Future Tense', 'type': 'rss', 'htmlUrl': 'http://www.publicradio.org/columns/futuretense/'}&lt;br /&gt;outline {'xmlUrl': 'http://www.npr.org/rss/podcast.php?id=510030', 'text': 'Engines Of Our Ingenuity Podcast', 'type': 'rss', 'htmlUrl': 'http://www.uh.edu/engines/engines.htm'}&lt;br /&gt;outline {'xmlUrl': 'http://www.nyas.org/Podcasts/Atom.axd', 'text': 'Science &amp;amp; the City', 'type': 'rss', 'htmlUrl': 'http://www.nyas.org/WhatWeDo/SciencetheCity.aspx'}&lt;br /&gt;outline {'text': 'Books and Fiction'}&lt;br /&gt;outline {'xmlUrl': 'http://feeds.feedburner.com/podiobooks', 'text': 'Podiobooker', 'type': 'rss', 'htmlUrl': 'http://www.podiobooks.com/blog'}&lt;br /&gt;outline {'xmlUrl': 'http://web.me.com/normsherman/Site/Podcast/rss.xml', 'text': 'The Drabblecast', 'type': 'rss', 'htmlUrl': 'http://web.me.com/normsherman/Site/Podcast/Podcast.html'}&lt;br /&gt;outline {'xmlUrl': 'http://www.tor.com/rss/category/TorDotStories', 'text': 'tor.com / category / tordotstories', 'type': 'rss', 'htmlUrl': 'http://www.tor.com/'}&lt;br /&gt;outline {'text': 'Computers and Programming'}&lt;br /&gt;outline {'xmlUrl': 'http://leo.am/podcasts/mbw', 'text': 'MacBreak Weekly', 'type': 'rss', 'htmlUrl': 'http://twit.tv/mbw'}&lt;br /&gt;outline {'xmlUrl': 'http://leo.am/podcasts/floss', 'text': 'FLOSS Weekly', 'type': 'rss', 'htmlUrl': 'http://twit.tv'}&lt;br /&gt;outline {'xmlUrl': 'http://www.coreint.org/podcast.xml', 'text': 'Core Intuition', 'type': 'rss', 'htmlUrl': 'http://www.coreint.org/'}&lt;br /&gt;outline {'text': 'Python'}&lt;br /&gt;outline {'xmlUrl': 'http://advocacy.python.org/podcasts/pycon.rss', 'text': 'PyCon Podcast', 'type': 'rss', 'htmlUrl': 'http://advocacy.python.org/podcasts/'}&lt;br /&gt;outline {'xmlUrl': 'http://advocacy.python.org/podcasts/littlebit.rss', 'text': 'A Little Bit of Python', 'type': 'rss', 'htmlUrl': 'http://advocacy.python.org/podcasts/'}&lt;br /&gt;outline {'xmlUrl': 'http://djangodose.com/everything/feed/', 'text': 'Django Dose Everything Feed', 'type': 'rss'}&lt;br /&gt;outline {'text': 'Miscelaneous'}&lt;br /&gt;outline {'xmlUrl': 'http://www.castsampler.com/cast/feed/rss/dhellmann/', 'text': "dhellmann's CastSampler Feed", 'type': 'rss', 'htmlUrl': 'http://www.castsampler.com/users/dhellmann/'}&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;If we wanted to print only the groups of names and feed URLs for the&lt;br /&gt;podcasts, leaving out of all of the data in the header section, we&lt;br /&gt;could iterate over only just the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;outline&lt;/span&gt;&lt;/tt&gt; nodes and print the&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;text&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;xmlUrl&lt;/span&gt;&lt;/tt&gt; attributes.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;podcasts.opml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getiterator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;outline&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;xmlUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; :: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Because we passed &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;'outline'&lt;/span&gt;&lt;/tt&gt; to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;tree.getiterator()&lt;/span&gt;&lt;/tt&gt; processing is&lt;br /&gt;limited to only nodes with the tag &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;'outline'&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_show_feed_urls.py&lt;br /&gt;Science and Tech&lt;br /&gt;  APM: Future Tense :: http://www.publicradio.org/columns/futuretense/podcast.xml&lt;br /&gt;  Engines Of Our Ingenuity Podcast :: http://www.npr.org/rss/podcast.php?id=510030&lt;br /&gt;  Science &amp;amp; the City :: http://www.nyas.org/Podcasts/Atom.axd&lt;br /&gt;Books and Fiction&lt;br /&gt;  Podiobooker :: http://feeds.feedburner.com/podiobooks&lt;br /&gt;  The Drabblecast :: http://web.me.com/normsherman/Site/Podcast/rss.xml&lt;br /&gt;  tor.com / category / tordotstories :: http://www.tor.com/rss/category/TorDotStories&lt;br /&gt;Computers and Programming&lt;br /&gt;  MacBreak Weekly :: http://leo.am/podcasts/mbw&lt;br /&gt;  FLOSS Weekly :: http://leo.am/podcasts/floss&lt;br /&gt;  Core Intuition :: http://www.coreint.org/podcast.xml&lt;br /&gt;Python&lt;br /&gt;  PyCon Podcast :: http://advocacy.python.org/podcasts/pycon.rss&lt;br /&gt;  A Little Bit of Python :: http://advocacy.python.org/podcasts/littlebit.rss&lt;br /&gt;  Django Dose Everything Feed :: http://djangodose.com/everything/feed/&lt;br /&gt;Miscelaneous&lt;br /&gt;  dhellmann's CastSampler Feed :: http://www.castsampler.com/cast/feed/rss/dhellmann/&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="finding-nodes-in-a-document"&gt;&lt;h2&gt;Finding Nodes in a Document&lt;/h2&gt;&lt;p&gt;Walking the entire tree yourself like this searching for relevant&lt;br /&gt;nodes can be error prone.  In the example above, we had to look at&lt;br /&gt;each outline node to determine if it was a group (nodes with only a&lt;br /&gt;&amp;#8220;text&amp;#8221; attribute) or podcast (with both &amp;#8220;text&amp;#8221; and &amp;#8220;xmlUrl&amp;#8221;).  If we&lt;br /&gt;were writing a podcast downloader and needed to produce a simple list&lt;br /&gt;of the podcast feed URLs, without names or groups, we might simplify&lt;br /&gt;the logic using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;findall()&lt;/span&gt;&lt;/tt&gt; to look for nodes with more descriptive&lt;br /&gt;search characteristics.&lt;/p&gt;&lt;p&gt;A first pass at converting the above example might construct an XPath&lt;br /&gt;argument to look for all outline nodes.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;podcasts.opml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.//outline&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;xmlUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The logic in this version is not substantially different than the&lt;br /&gt;version using &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;getiterator()&lt;/span&gt;&lt;/tt&gt;.  We still have to check for the&lt;br /&gt;presence of the URL, except that we don&amp;#8217;t print the group name when&lt;br /&gt;the URL is not found.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_find_feeds_by_tag.py&lt;br /&gt;http://www.publicradio.org/columns/futuretense/podcast.xml&lt;br /&gt;http://www.npr.org/rss/podcast.php?id=510030&lt;br /&gt;http://www.nyas.org/Podcasts/Atom.axd&lt;br /&gt;http://feeds.feedburner.com/podiobooks&lt;br /&gt;http://web.me.com/normsherman/Site/Podcast/rss.xml&lt;br /&gt;http://www.tor.com/rss/category/TorDotStories&lt;br /&gt;http://leo.am/podcasts/mbw&lt;br /&gt;http://leo.am/podcasts/floss&lt;br /&gt;http://www.coreint.org/podcast.xml&lt;br /&gt;http://advocacy.python.org/podcasts/pycon.rss&lt;br /&gt;http://advocacy.python.org/podcasts/littlebit.rss&lt;br /&gt;http://djangodose.com/everything/feed/&lt;br /&gt;http://www.castsampler.com/cast/feed/rss/dhellmann/&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Another version can take advantage of the fact that we know the&lt;br /&gt;outline nodes are only nested two levels deep.  If we change the&lt;br /&gt;search path to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;.//outline/outline&lt;/span&gt;&lt;/tt&gt; we will process only the second&lt;br /&gt;level of outline nodes.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;podcasts.opml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;findall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;.//outline/outline&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;xmlUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;url&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;We expect all of those outline nodes nested 2 levels deep in the input&lt;br /&gt;will have the xmlURL attribute refering to the podcast feed, so if we&lt;br /&gt;were brave we could skip checking for for the attribute before using&lt;br /&gt;it.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_find_feeds_by_structure.py&lt;br /&gt;http://www.publicradio.org/columns/futuretense/podcast.xml&lt;br /&gt;http://www.npr.org/rss/podcast.php?id=510030&lt;br /&gt;http://www.nyas.org/Podcasts/Atom.axd&lt;br /&gt;http://feeds.feedburner.com/podiobooks&lt;br /&gt;http://web.me.com/normsherman/Site/Podcast/rss.xml&lt;br /&gt;http://www.tor.com/rss/category/TorDotStories&lt;br /&gt;http://leo.am/podcasts/mbw&lt;br /&gt;http://leo.am/podcasts/floss&lt;br /&gt;http://www.coreint.org/podcast.xml&lt;br /&gt;http://advocacy.python.org/podcasts/pycon.rss&lt;br /&gt;http://advocacy.python.org/podcasts/littlebit.rss&lt;br /&gt;http://djangodose.com/everything/feed/&lt;br /&gt;http://www.castsampler.com/cast/feed/rss/dhellmann/&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;This version is limited to our existing structure, though, so if the&lt;br /&gt;outline nodes are ever rearranged into a deeper tree it will stop&lt;br /&gt;working.&lt;/p&gt;&lt;/div&gt;&lt;div class="section" id="parsed-node-attributes"&gt;&lt;h2&gt;Parsed Node Attributes&lt;/h2&gt;&lt;p&gt;The items returned by &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;findall()&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;getiterator()&lt;/span&gt;&lt;/tt&gt; are Element&lt;br /&gt;objects, each representing a node in the XML parse tree.  Each Element&lt;br /&gt;has attributes for accessing data pulled out of the XML.  This can be&lt;br /&gt;illustrated with a somewhat more contrived example input file,&lt;br /&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;data.xml&lt;/span&gt;&lt;/tt&gt;:&lt;/p&gt;&lt;div class="highlight-xml"&gt;&lt;table class="highlighttable"&gt;&lt;tr&gt;&lt;td class="linenos"&gt;&lt;div class="linenodiv"&gt;&lt;pre&gt;1&lt;br /&gt;2&lt;br /&gt;3&lt;br /&gt;4&lt;br /&gt;5&lt;br /&gt;6&lt;br /&gt;7&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="cp"&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nt"&gt;&amp;lt;top&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;child&amp;gt;&lt;/span&gt;This child contains text.&lt;span class="nt"&gt;&amp;lt;/child&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;child_with_tail&amp;gt;&lt;/span&gt;This child has regular text.&lt;span class="nt"&gt;&amp;lt;/child_with_tail&amp;gt;&lt;/span&gt;And &amp;quot;tail&amp;quot; text.&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;with_attributes&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;foo=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&lt;br /&gt;  &lt;span class="nt"&gt;&amp;lt;entity_expansion&lt;/span&gt; &lt;span class="na"&gt;attribute=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;This &amp;amp;#38; That&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;That &lt;span class="ni"&gt;&amp;amp;#38;&lt;/span&gt; This&lt;span class="nt"&gt;&amp;lt;/entity_expansion&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="nt"&gt;&amp;lt;/top&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;p&gt;The &amp;#8220;attributes&amp;#8221; of a node are available in the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;attrib&lt;/span&gt;&lt;/tt&gt; property,&lt;br /&gt;which acts like a dictionary.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;data.xml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;./with_attributes&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  &lt;/span&gt;&lt;span class="si"&gt;%-4s&lt;/span&gt;&lt;span class="s"&gt; = &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The node on line 5 of the input file has 2 attributes, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;name&lt;/span&gt;&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;foo&lt;/span&gt;&lt;/tt&gt;.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_node_attributes.py&lt;br /&gt;with_attributes&lt;br /&gt;  foo  = "bar"&lt;br /&gt;  name = "value"&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;The text content of the nodes is available, along with the &amp;#8220;tail&amp;#8221; text&lt;br /&gt;that comes after the end of a close tag.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;data.xml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;./child&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;./child_with_tail&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;]:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  child node text:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  and tail text  :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;child&lt;/span&gt;&lt;/tt&gt; node on line 3 contains embedded text, and the node on&lt;br /&gt;line 4 has text with a tail (including any whitespace).&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_node_text.py&lt;br /&gt;child&lt;br /&gt;  child node text: This child contains text.&lt;br /&gt;  and tail text  :&lt;br /&gt;&lt;br /&gt;child_with_tail&lt;br /&gt;  child node text: This child has regular text.&lt;br /&gt;  and tail text  : And "tail" text.&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Conveniently, XML entity references embedded in the document are&lt;br /&gt;converted to the appropriate characters before values are returned.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;data.xml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ElementTree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;node&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;entity_expansion&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  in attribute:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;attribute&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  in text     :&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;The conversion saves you from having to worry about an implementation&lt;br /&gt;detail of representing certain characters in an XML document.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_entity_references.py&lt;br /&gt;entity_expansion&lt;br /&gt;  in attribute: This &amp;amp; That&lt;br /&gt;  in text     : That &amp;amp; This&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="watching-events-while-parsing"&gt;&lt;h2&gt;Watching Events While Parsing&lt;/h2&gt;&lt;p&gt;The other API useful for processing XML documents is event-based.  The&lt;br /&gt;parser generates &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;start&lt;/span&gt;&lt;/tt&gt; events for opening tags and &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;end&lt;/span&gt;&lt;/tt&gt; events&lt;br /&gt;for closing tags.  Iterating over the event stream lets you extract&lt;br /&gt;data from the document while parsing it, which is convenient if you&lt;br /&gt;don&amp;#8217;t need to manipulate the entire document afterwards and if you&lt;br /&gt;want to avoid holding the entire parsed document in memory.&lt;/p&gt;&lt;p&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;iterparse()&lt;/span&gt;&lt;/tt&gt; returns an iterable that produces tuples containing&lt;br /&gt;the name of the event and the node triggering the event.  Events can&lt;br /&gt;be one of:&lt;/p&gt;&lt;dl class="docutils"&gt;&lt;dt&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;start&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;A new tag has been encountered.  The closing angle bracket of the&lt;br /&gt;tag was processed, but not the contents.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;end&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;The closing angle bracket of a closing tag has been processed.  All&lt;br /&gt;of the children were already processed.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;start-ns&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;Start a namespace declaration.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;end-ns&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;End a namespace declaration.&lt;/dd&gt;&lt;/dl&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree.ElementTree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;iterparse&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;prefix_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;prefix_dots&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;.&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;prefix_width&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;line_template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;{prefix:&amp;lt;0.{prefix_len}}{event:&amp;lt;8}{suffix:&amp;lt;{suffix_len}} {node.tag:&amp;lt;12} {node_id}&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;iterparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;podcasts.opml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;start&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;start-ns&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;end-ns&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;end&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="n"&gt;prefix_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;line_template&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prefix_dots&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;                               &lt;span class="n"&gt;prefix_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prefix_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;                               &lt;span class="n"&gt;suffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;                               &lt;span class="n"&gt;suffix_len&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix_width&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;prefix_len&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;br /&gt;                               &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;                               &lt;span class="n"&gt;node_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;br /&gt;                               &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br /&gt;                               &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;start&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;depth&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;By default, only &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;end&lt;/span&gt;&lt;/tt&gt; events are generated.  To see other events,&lt;br /&gt;pass the list of event names you want to receive to &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;iterparse()&lt;/span&gt;&lt;/tt&gt;,&lt;br /&gt;as in this example:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_show_all_events.py&lt;br /&gt;start            opml         876256&lt;br /&gt;..start          head         876336&lt;br /&gt;....start        title        888920&lt;br /&gt;....end          title        888920&lt;br /&gt;....start        dateCreated  889280&lt;br /&gt;....end          dateCreated  889280&lt;br /&gt;....start        dateModified 889320&lt;br /&gt;....end          dateModified 889320&lt;br /&gt;..end            head         876336&lt;br /&gt;..start          body         889400&lt;br /&gt;....start        outline      889560&lt;br /&gt;......start      outline      889600&lt;br /&gt;......end        outline      889600&lt;br /&gt;......start      outline      889480&lt;br /&gt;......end        outline      889480&lt;br /&gt;......start      outline      889680&lt;br /&gt;......end        outline      889680&lt;br /&gt;....end          outline      889560&lt;br /&gt;....start        outline      889720&lt;br /&gt;......start      outline      889760&lt;br /&gt;......end        outline      889760&lt;br /&gt;......start      outline      889840&lt;br /&gt;......end        outline      889840&lt;br /&gt;......start      outline      889920&lt;br /&gt;......end        outline      889920&lt;br /&gt;....end          outline      889720&lt;br /&gt;....start        outline      889880&lt;br /&gt;......start      outline      890040&lt;br /&gt;......end        outline      890040&lt;br /&gt;......start      outline      890120&lt;br /&gt;......end        outline      890120&lt;br /&gt;......start      outline      890200&lt;br /&gt;......end        outline      890200&lt;br /&gt;....end          outline      889880&lt;br /&gt;....start        outline      890240&lt;br /&gt;......start      outline      890360&lt;br /&gt;......end        outline      890360&lt;br /&gt;......start      outline      890440&lt;br /&gt;......end        outline      890440&lt;br /&gt;......start      outline      890520&lt;br /&gt;......end        outline      890520&lt;br /&gt;....end          outline      890240&lt;br /&gt;....start        outline      890640&lt;br /&gt;......start      outline      890720&lt;br /&gt;......end        outline      890720&lt;br /&gt;....end          outline      890640&lt;br /&gt;..end            body         889400&lt;br /&gt;end              opml         876256&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;The event-style of processing may be more natural for some operations,&lt;br /&gt;such as converting XML input to some other format.  For example,&lt;br /&gt;suppose we want to convert the list of podcasts we have been working&lt;br /&gt;with from an XML file to a data file we can load into a spreadsheet or&lt;br /&gt;database application.  We don&amp;#8217;t need to hold the entire data set in&lt;br /&gt;memory at a time, since we&amp;#8217;re simply changing the format.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;csv&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree.ElementTree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;iterparse&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quoting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QUOTE_NONNUMERIC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;group_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;iterparse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;podcasts.opml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;events&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;start&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;outline&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Ignore anything not part of the outline&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;continue&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;xmlUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Remember the current group&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;group_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Output a podcast entry&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;br /&gt;                          &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;xmlUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;br /&gt;                          &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;htmlUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;br /&gt;                          &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                         &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;This example program converts our podcast list to a CSV file, ready to&lt;br /&gt;be imported into another application.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_write_podcast_csv.py&lt;br /&gt;"Science and Tech","APM: Future Tense","http://www.publicradio.org/columns/futuretense/podcast.xml","http://www.publicradio.org/columns/futuretense/"&lt;br /&gt;"Science and Tech","Engines Of Our Ingenuity Podcast","http://www.npr.org/rss/podcast.php?id=510030","http://www.uh.edu/engines/engines.htm"&lt;br /&gt;"Science and Tech","Science &amp;amp; the City","http://www.nyas.org/Podcasts/Atom.axd","http://www.nyas.org/WhatWeDo/SciencetheCity.aspx"&lt;br /&gt;"Books and Fiction","Podiobooker","http://feeds.feedburner.com/podiobooks","http://www.podiobooks.com/blog"&lt;br /&gt;"Books and Fiction","The Drabblecast","http://web.me.com/normsherman/Site/Podcast/rss.xml","http://web.me.com/normsherman/Site/Podcast/Podcast.html"&lt;br /&gt;"Books and Fiction","tor.com / category / tordotstories","http://www.tor.com/rss/category/TorDotStories","http://www.tor.com/"&lt;br /&gt;"Computers and Programming","MacBreak Weekly","http://leo.am/podcasts/mbw","http://twit.tv/mbw"&lt;br /&gt;"Computers and Programming","FLOSS Weekly","http://leo.am/podcasts/floss","http://twit.tv"&lt;br /&gt;"Computers and Programming","Core Intuition","http://www.coreint.org/podcast.xml","http://www.coreint.org/"&lt;br /&gt;"Python","PyCon Podcast","http://advocacy.python.org/podcasts/pycon.rss","http://advocacy.python.org/podcasts/"&lt;br /&gt;"Python","A Little Bit of Python","http://advocacy.python.org/podcasts/littlebit.rss","http://advocacy.python.org/podcasts/"&lt;br /&gt;"Python","Django Dose Everything Feed","http://djangodose.com/everything/feed/",""&lt;br /&gt;"Miscelaneous","dhellmann's CastSampler Feed","http://www.castsampler.com/cast/feed/rss/dhellmann/","http://www.castsampler.com/users/dhellmann/"&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="creating-your-own-tree-builder"&gt;&lt;h2&gt;Creating Your Own Tree Builder&lt;/h2&gt;&lt;p&gt;A potentially more efficient means of handling parse events is to&lt;br /&gt;replace the standard tree builder behavior with your own.  The&lt;br /&gt;ElementTree parser uses an XMLTreeBuilder to process the XML and call&lt;br /&gt;methods on a target class to save the results.  The usual output is an&lt;br /&gt;ElementTree instance created by the default TreeBuilder class.  By&lt;br /&gt;replacing TreeBuilder with your own class, you can receive the events&lt;br /&gt;before the Element nodes are instantiated, saving that portion of the&lt;br /&gt;overhead.&lt;/p&gt;&lt;p&gt;The XML-to-CSV app from the previous section can be translated to a&lt;br /&gt;tree builder.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;csv&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree.ElementTree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XMLTreeBuilder&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PodcastListToCSV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;outputFile&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;quoting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;QUOTE_NONNUMERIC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;outline&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="c"&gt;# Ignore anything not part of the outline&lt;/span&gt;&lt;br /&gt;            &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;xmlUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;            &lt;span class="c"&gt;# Remember the current group&lt;/span&gt;&lt;br /&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;            &lt;span class="c"&gt;# Output a podcast entry&lt;/span&gt;&lt;br /&gt;            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;writerow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;group_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;br /&gt;                                   &lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;xmlUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;br /&gt;                                   &lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;htmlUrl&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;br /&gt;                                   &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;                                  &lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Ignore closing tags&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;pass&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Ignore data inside nodes&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;pass&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;&lt;br /&gt;        &lt;span class="c"&gt;# Nothing special to do here&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;return&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PodcastListToCSV&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;XMLTreeBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;podcasts.opml&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;rt&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br /&gt;        &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;feed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;PodcastListToCSV&lt;/span&gt;&lt;/tt&gt; implements the TreeBuilder protocol.  Each time a&lt;br /&gt;new XML tag is encountered, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;start()&lt;/span&gt;&lt;/tt&gt; is called with the tag name&lt;br /&gt;and attributes.  When a closing tag is seen &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;end()&lt;/span&gt;&lt;/tt&gt; is called with&lt;br /&gt;the name.  In between, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;data()&lt;/span&gt;&lt;/tt&gt; is called when a node has content&lt;br /&gt;(the tree builder is expected to keep up with the &amp;#8220;current&amp;#8221; node).&lt;br /&gt;When all of the input is processed, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;close()&lt;/span&gt;&lt;/tt&gt; is called.  It can&lt;br /&gt;return a value, which will be returned to the user of the&lt;br /&gt;XMLTreeBuilder.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_podcast_csv_treebuilder.py&lt;br /&gt;"Science and Tech","APM: Future Tense","http://www.publicradio.org/columns/futuretense/podcast.xml","http://www.publicradio.org/columns/futuretense/"&lt;br /&gt;"Science and Tech","Engines Of Our Ingenuity Podcast","http://www.npr.org/rss/podcast.php?id=510030","http://www.uh.edu/engines/engines.htm"&lt;br /&gt;"Science and Tech","Science &amp;amp; the City","http://www.nyas.org/Podcasts/Atom.axd","http://www.nyas.org/WhatWeDo/SciencetheCity.aspx"&lt;br /&gt;"Books and Fiction","Podiobooker","http://feeds.feedburner.com/podiobooks","http://www.podiobooks.com/blog"&lt;br /&gt;"Books and Fiction","The Drabblecast","http://web.me.com/normsherman/Site/Podcast/rss.xml","http://web.me.com/normsherman/Site/Podcast/Podcast.html"&lt;br /&gt;"Books and Fiction","tor.com / category / tordotstories","http://www.tor.com/rss/category/TorDotStories","http://www.tor.com/"&lt;br /&gt;"Computers and Programming","MacBreak Weekly","http://leo.am/podcasts/mbw","http://twit.tv/mbw"&lt;br /&gt;"Computers and Programming","FLOSS Weekly","http://leo.am/podcasts/floss","http://twit.tv"&lt;br /&gt;"Computers and Programming","Core Intuition","http://www.coreint.org/podcast.xml","http://www.coreint.org/"&lt;br /&gt;"Python","PyCon Podcast","http://advocacy.python.org/podcasts/pycon.rss","http://advocacy.python.org/podcasts/"&lt;br /&gt;"Python","A Little Bit of Python","http://advocacy.python.org/podcasts/littlebit.rss","http://advocacy.python.org/podcasts/"&lt;br /&gt;"Python","Django Dose Everything Feed","http://djangodose.com/everything/feed/",""&lt;br /&gt;"Miscelaneous","dhellmann's CastSampler Feed","http://www.castsampler.com/cast/feed/rss/dhellmann/","http://www.castsampler.com/users/dhellmann/"&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="parsing-strings"&gt;&lt;h2&gt;Parsing Strings&lt;/h2&gt;&lt;p&gt;To work with smaller bits of XML text, especially string literals as&lt;br /&gt;might be embedded in the source of a program, use&lt;br /&gt;xml.etree.ElementTree.XML and pass a single argument, the string&lt;br /&gt;containing the XML to be parsed.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree.ElementTree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XML&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;XML&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;&amp;lt;root&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;  &amp;lt;group&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;    &amp;lt;child id=&amp;quot;a&amp;quot;&amp;gt;This is child &amp;quot;a&amp;quot;.&amp;lt;/child&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;    &amp;lt;child id=&amp;quot;b&amp;quot;&amp;gt;This is child &amp;quot;b&amp;quot;.&amp;lt;/child&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;  &amp;lt;/group&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;  &amp;lt;group&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;    &amp;lt;child id=&amp;quot;c&amp;quot;&amp;gt;This is child &amp;quot;c&amp;quot;.&amp;lt;/child&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;  &amp;lt;/group&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;&amp;lt;/root&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;parsed =&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parsed&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;parsed&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getiterator&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tag&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  text: &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  tail: &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;elem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;attrib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;&lt;br /&gt;        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;  &lt;/span&gt;&lt;span class="si"&gt;%-4s&lt;/span&gt;&lt;span class="s"&gt; = &amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Notice that unlike with &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;parse()&lt;/span&gt;&lt;/tt&gt;, the return value is an Element&lt;br /&gt;instance instead of an ElementTree.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_XML.py&lt;br /&gt;parsed = &amp;lt;Element root at d4e40&amp;gt;&lt;br /&gt;root&lt;br /&gt;&lt;br /&gt;group&lt;br /&gt;&lt;br /&gt;child&lt;br /&gt;  text: "This is child "a"."&lt;br /&gt;  id   = "a"&lt;br /&gt;&lt;br /&gt;child&lt;br /&gt;  text: "This is child "b"."&lt;br /&gt;  id   = "b"&lt;br /&gt;&lt;br /&gt;group&lt;br /&gt;&lt;br /&gt;child&lt;br /&gt;  text: "This is child "c"."&lt;br /&gt;  id   = "c"&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;For structured XML that uses the &amp;#8220;id&amp;#8221; attribute to identify unique&lt;br /&gt;nodes of interest, &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;XMLID()&lt;/span&gt;&lt;/tt&gt; is a convenient way to access the parse&lt;br /&gt;results.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;xml.etree.ElementTree&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XMLID&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id_map&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;XMLID&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;&amp;lt;root&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;  &amp;lt;group&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;    &amp;lt;child id=&amp;quot;a&amp;quot;&amp;gt;This is child &amp;quot;a&amp;quot;.&amp;lt;/child&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;    &amp;lt;child id=&amp;quot;b&amp;quot;&amp;gt;This is child &amp;quot;b&amp;quot;.&amp;lt;/child&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;  &amp;lt;/group&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;  &amp;lt;group&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;    &amp;lt;child id=&amp;quot;c&amp;quot;&amp;gt;This is child &amp;quot;c&amp;quot;.&amp;lt;/child&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;  &amp;lt;/group&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;&amp;lt;/root&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id_map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;()):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; = &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;    &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;XMLID()&lt;/span&gt;&lt;/tt&gt; returns the parsed tree as an Element object,&lt;br /&gt;along with a dictionary mapping the id attribute strings to the&lt;br /&gt;individual nodes in the tree.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python ElementTree_XMLID.py&lt;br /&gt;a = &amp;lt;Element child at d3eb8&amp;gt;&lt;br /&gt;b = &amp;lt;Element child at d3d78&amp;gt;&lt;br /&gt;c = &amp;lt;Element child at d9030&amp;gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;Outline Processor Markup Language, &lt;a class="reference external" href="http://www.opml.org/"&gt;OPML&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Dave Winer&amp;#8217;s OPML specification and documentation.&lt;/dd&gt;&lt;dt&gt;&lt;a class="reference external" href="http://effbot.org/zone/element-xpath.htm"&gt;XPath Support in ElementTree&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;Part of Fredrick Lundh&amp;#8217;s original documentation for ElementTree.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;csv&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;Read and write comma-separated-value files&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The &lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/xml/etree/ElementTree/parse.html"&gt;canonical version&lt;/a&gt; of this article&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-2248271756635298269?l=blog.doughellmann.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=SN85IUHrdek:BDO1skGT8LU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=SN85IUHrdek:BDO1skGT8LU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?i=SN85IUHrdek:BDO1skGT8LU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=SN85IUHrdek:BDO1skGT8LU:bcOpcFrp8Mo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?d=bcOpcFrp8Mo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=SN85IUHrdek:BDO1skGT8LU:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?i=SN85IUHrdek:BDO1skGT8LU:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=SN85IUHrdek:BDO1skGT8LU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=SN85IUHrdek:BDO1skGT8LU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?i=SN85IUHrdek:BDO1skGT8LU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DougHellmann/~4/SN85IUHrdek" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/2248271756635298269/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=2248271756635298269" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/2248271756635298269?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/2248271756635298269?v=2" /><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/SN85IUHrdek/pymotw-parsing-xml-documents-with.html" title="PyMOTW: Parsing XML Documents with ElementTree" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00116818175230541568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.doughellmann.com/2010/03/pymotw-parsing-xml-documents-with.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEAFQng7eip7ImA9WxBUGUo.&quot;"><id>tag:blogger.com,1999:blog-5440028356946346379.post-486143239880400158</id><published>2010-03-07T09:38:00.001-05:00</published><updated>2010-03-07T09:38:33.602-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-07T09:38:33.602-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="PyMOTW" /><title>PyMOTW: tabnanny - Indentation validator</title><content type="html">&lt;div class="section" id="module-tabnanny"&gt;&lt;h1&gt;tabnanny &amp;#8211; Indentation validator&lt;/h1&gt;&lt;table class="docutils field-list" frame="void" rules="none"&gt;&lt;col class="field-name" /&gt;&lt;col class="field-body" /&gt;&lt;tbody valign="top"&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Purpose:&lt;/th&gt;&lt;td class="field-body"&gt;Scan Python source code looking for suspicious indentation.&lt;/td&gt;&lt;/tr&gt;&lt;tr class="field"&gt;&lt;th class="field-name"&gt;Python Version:&lt;/th&gt;&lt;td class="field-body"&gt;2.1.3 and later&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Consistent use of indentation is important in a langauge like Python,&lt;br /&gt;where white-space is significant.  The tabnanny module provides a&lt;br /&gt;scanner to report on &amp;#8220;ambiguous&amp;#8221; use of indentation.&lt;/p&gt;&lt;div class="section" id="running-from-the-command-line"&gt;&lt;h2&gt;Running from the Command Line&lt;/h2&gt;&lt;p&gt;The simplest way to use tabnanny is to run it from the command line,&lt;br /&gt;passing the names of files to check.  If you pass directory names, the&lt;br /&gt;directories are scanned recursively to find &lt;cite&gt;.py&lt;/cite&gt; files to check.&lt;/p&gt;&lt;p&gt;When I ran tabnanny across the PyMOTW source code, I found one old&lt;br /&gt;module with tabs instead of spaces:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python -m tabnanny .&lt;br /&gt;./PyMOTW/Queue/fetch_podcasts.py 78 "\t\tfor enclosure in entry.get('enclosures', []):\n"&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;Sure enough, line 78 of &lt;cite&gt;fetch_podcasts.py&lt;/cite&gt; had two tabs instead of 8&lt;br /&gt;spaces.  I didn&amp;#8217;t see this by looking at it in my editor because I&lt;br /&gt;have my tabstops set to 4 spaces, so visually there was no difference.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;enclosure&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;enclosures&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;&lt;br /&gt;    &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Queuing:&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;enclosure&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;url&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;enclosure_queue&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;enclosure&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;url&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Correcting line 78 and running tabnanny again showed another error on&lt;br /&gt;line 79.  One last problem showed up on line 80.&lt;/p&gt;&lt;p&gt;If you want to scan files, but not see the details about the error,&lt;br /&gt;you can use the &lt;cite&gt;-q&lt;/cite&gt; option to suppress all information except the&lt;br /&gt;filename.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python -m tabnanny -q .&lt;br /&gt;./PyMOTW/Queue/fetch_podcasts.py&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;To see more information about the files being scanned, use the &lt;cite&gt;-v&lt;/cite&gt; option.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python -m tabnanny -v ./PyMOTW/Queue&lt;br /&gt;'./PyMOTW/Queue': listing directory&lt;br /&gt;'./PyMOTW/Queue/__init__.py': Clean bill of health.&lt;br /&gt;'./PyMOTW/Queue/feedparser.py': Clean bill of health.&lt;br /&gt;'./PyMOTW/Queue/fetch_podcasts.py': *** Line 78: trouble in tab city! ***&lt;br /&gt;offending line: "\t\tfor enclosure in entry.get('enclosures', []):\n"&lt;br /&gt;indent not greater e.g. at tab sizes 1, 2&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="section" id="using-within-your-program"&gt;&lt;h2&gt;Using within Your Program&lt;/h2&gt;&lt;p&gt;As soon as I discovered the mistake in my Queue example, I decided I&lt;br /&gt;needed to add a tabnanny check to my PyMOTW build process.  I created&lt;br /&gt;a tabcheck task in my pavement.py build script so I could run &lt;cite&gt;paver&lt;br /&gt;tabcheck&lt;/cite&gt; and scan the code I&amp;#8217;m working on for PyMOTW.  This is&lt;br /&gt;possible because tabnanny exposes its &lt;cite&gt;check()&lt;/cite&gt; function as a public&lt;br /&gt;API.&lt;/p&gt;&lt;p&gt;Here&amp;#8217;s an example of using tabnanny that doesn&amp;#8217;t require understanding&lt;br /&gt;Paver&amp;#8217;s task definition decorators.&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;&lt;br /&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;tabnanny&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="c"&gt;# Turn on verbose mode&lt;/span&gt;&lt;br /&gt;&lt;span class="n"&gt;tabnanny&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dirname&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]:&lt;/span&gt;&lt;br /&gt;    &lt;span class="n"&gt;tabnanny&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;And in action:&lt;/p&gt;&lt;div class="highlight-python"&gt;&lt;pre&gt;$ python tabnanny_check.py ../Queue&lt;br /&gt;'../Queue': listing directory&lt;br /&gt;'../Queue/__init__.py': Clean bill of health.&lt;br /&gt;'../Queue/feedparser.py': Clean bill of health.&lt;br /&gt;'../Queue/fetch_podcasts.py': *** Line 78: trouble in tab city! ***&lt;br /&gt;offending line: "\t\tfor enclosure in entry.get('enclosures', []):\n"&lt;br /&gt;indent not greater e.g. at tab sizes 1, 2&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="admonition note"&gt;&lt;p class="first admonition-title"&gt;Note&lt;/p&gt;&lt;p class="last"&gt;If you run these examples against the PyMOTW code it won&amp;#8217;t report&lt;br /&gt;the same errors, since I have fixed my code in this release.&lt;/p&gt;&lt;/div&gt;&lt;div class="admonition-see-also admonition seealso"&gt;&lt;p class="first admonition-title"&gt;See also&lt;/p&gt;&lt;dl class="last docutils"&gt;&lt;dt&gt;&lt;a class="reference external" href="http://docs.python.org/library/tabnanny.html"&gt;tabnanny&lt;/a&gt;&lt;/dt&gt;&lt;dd&gt;The standard library documentation for this module.&lt;/dd&gt;&lt;dt&gt;&lt;tt class="xref docutils literal"&gt;&lt;span class="pre"&gt;tokenize&lt;/span&gt;&lt;/tt&gt;&lt;/dt&gt;&lt;dd&gt;Lexical scanner for Python source code.&lt;/dd&gt;&lt;/dl&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/"&gt;PyMOTW Home&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The &lt;a class="reference external" href="http://www.doughellmann.com/PyMOTW/tabnanny/"&gt;canonical version&lt;/a&gt; of this article&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-486143239880400158?l=blog.doughellmann.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=FzgqNrcDZ7c:bVSft9ehPEA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=FzgqNrcDZ7c:bVSft9ehPEA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?i=FzgqNrcDZ7c:bVSft9ehPEA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=FzgqNrcDZ7c:bVSft9ehPEA:bcOpcFrp8Mo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?d=bcOpcFrp8Mo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=FzgqNrcDZ7c:bVSft9ehPEA:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?i=FzgqNrcDZ7c:bVSft9ehPEA:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=FzgqNrcDZ7c:bVSft9ehPEA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=FzgqNrcDZ7c:bVSft9ehPEA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?i=FzgqNrcDZ7c:bVSft9ehPEA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DougHellmann/~4/FzgqNrcDZ7c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/486143239880400158/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=486143239880400158" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/486143239880400158?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/486143239880400158?v=2" /><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/FzgqNrcDZ7c/pymotw-tabnanny-indentation-validator.html" title="PyMOTW: tabnanny - Indentation validator" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00116818175230541568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.doughellmann.com/2010/03/pymotw-tabnanny-indentation-validator.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUAHRHY6eyp7ImA9WxBWEE4.&quot;"><id>tag:blogger.com,1999:blog-5440028356946346379.post-787741802895110624</id><published>2010-02-01T09:15:00.001-05:00</published><updated>2010-02-01T09:15:35.813-05:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-01T09:15:35.813-05:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="visualization" /><category scheme="http://www.blogger.com/atom/ns#" term="books" /><title>Book Review: Practical Virtualization Solutions</title><content type="html">&lt;em&gt;Practical Virtualization Solutions&lt;/em&gt; by Kenneth Hess and Amy Newman covers a lot of ground. From basic introduction to the technology itself, to advice about which of the big players to use now (and which to keep an eye on for the future), the authors walk you through all of the issues and potential gotchas of virtualization. Existing virtualization users may find the early parts of the book a little slow moving, but the advice in part 3 (“Hardware’s Role in Virtualization”) looks at issues like I/O virtualization that most of us haven’t seen before.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Why I picked it up:&lt;/strong&gt; I have some basic knowledge of and experience with VMware, but wanted learn more about Xen and Hyper-V.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Why I finished it:&lt;/strong&gt; It reads quickly and provides a good grounding in virtualization terms and technologies.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;I’d give it to:&lt;/strong&gt; Anyone looking into upgrading their infrastructure using modern virtualization tools.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.doughellmann.com/articles/bookreviews/practical_virtualization.html"&gt;Read more...&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/5440028356946346379-787741802895110624?l=blog.doughellmann.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=C6VhJ-49ATw:JbuBtra8O5A:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=C6VhJ-49ATw:JbuBtra8O5A:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?i=C6VhJ-49ATw:JbuBtra8O5A:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=C6VhJ-49ATw:JbuBtra8O5A:bcOpcFrp8Mo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?d=bcOpcFrp8Mo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=C6VhJ-49ATw:JbuBtra8O5A:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?i=C6VhJ-49ATw:JbuBtra8O5A:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=C6VhJ-49ATw:JbuBtra8O5A:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.doughellmann.com/~ff/DougHellmann?a=C6VhJ-49ATw:JbuBtra8O5A:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/DougHellmann?i=C6VhJ-49ATw:JbuBtra8O5A:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/DougHellmann/~4/C6VhJ-49ATw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://blog.doughellmann.com/feeds/787741802895110624/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=5440028356946346379&amp;postID=787741802895110624" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/787741802895110624?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/5440028356946346379/posts/default/787741802895110624?v=2" /><link rel="alternate" type="text/html" href="http://feeds.doughellmann.com/~r/DougHellmann/~3/C6VhJ-49ATw/book-review-practical-virtualization.html" title="Book Review: Practical Virtualization Solutions" /><author><name>Doug Hellmann</name><uri>http://www.blogger.com/profile/01892352754222143463</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="00116818175230541568" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://blog.doughellmann.com/2010/02/book-review-practical-virtualization.html</feedburner:origLink></entry></feed>
