{
  "attachments": [],
  "comments_archived": true,
  "date": "2004-09-01T10:47:41.000Z",
  "excerpt": "But, while I'm in the process of wheel reinvention, how about I borrow Kimbro's idea?  I just threw together a quick class called XPathDict, based on libxml2.",
  "layout": "post",
  "tags": [
    "hacks",
    "xml"
  ],
  "title": "XPath based Python dictionaries, on loan",
  "wordpress_id": 544,
  "wordpress_slug": "xpath-based-python-dictionaries-on-loan",
  "wordpress_url": "http://www.decafbad.com/blog/?p=544",
  "year": "2004",
  "month": "09",
  "day": "01",
  "isDir": false,
  "slug": "xpath-based-python-dictionaries-on-loan",
  "type": "entry",
  "postName": "2004-09-01-xpath-based-python-dictionaries-on-loan",
  "html": "<p>So <a href=\"http://www.xmldatabases.org/WK/blog\">Kimbro Staken</a> posted this nifty idea to build <a href=\"http://www.xmldatabases.org/WK/blog/1964_XPath_based_Python_Dictionaries.item\">XPath based Python dictionaries</a> to access XML data as a part of his incredibly nifty <a href=\"http://www.syncato.org/\">Syncato</a> microcontent management system.  Eventually, I've really got to break down and get that thing built and running on my server and my laptop-- it really seems like I'm reinventing so many wheels by not basing <a href=\"http://www.decafbad.com/cvs/dbagg3/\"><code>dbagg3</code></a> on it.</p>\n<p>But, while I'm in the process of wheel reinvention, how about I borrow Kimbro's idea?  I just threw together <a href=\"http://www.decafbad.com/cvs/*checkout*/dbagg3/lib/dbagg3/xmlutils.py\">a quick class called XPathDict</a>, based on <a href=\"http://www.xmlsoft.org/\">libxml2</a>.  It works a little something like this:</p>\n<pre><code>feed_xd = XPathDict(file=\"sample-atom.xml\")\nfor entry_node in feed_xd.nodes(\"//atom:entry\"):\n    entry = XPathDict(doc=entry_node.doc, node=entry_node)\n    print \"Title: \" % entry['atom:title']\n    if 'atom:author' in entry:\n        print \"Author: \" % entry['atom:author/atom:name']\n\nxml = \"\"\"\n   &lt;dbagg3:user xmlns=\"http://purl.org/atom/ns#\" \n            xmlns:dbagg3=\"http://decafbad.com/2004/07/dbagg3/\"&gt;\n        &lt;name&gt;deusx&lt;/name&gt;\n        &lt;email&gt;deus_x@pobox.com&lt;/email&gt;\n        &lt;url&gt;http://www.decafbad.com/&lt;/url&gt;\n        &lt;dbagg3:prefs&gt;\n            &lt;dbagg3:pref name=\"foo\"&gt;bar&lt;/dbagg3:pref&gt;\n        &lt;/dbagg3:prefs&gt;\n   &lt;/dbagg3:author&gt;\n\"\"\"\n\nmap = (\n    ('userName',  'a:name'),\n    ('userEmail', 'a:email'),\n    ('fooPref',   \"dbagg3:prefs/dbagg3:pref[@name='foo']\")\n)\n\nxd = XPathDict(xml=xml)\nxd.cd(\"/dbagg3:user\")\nprint xd.extract(map)\n\n#    {'userName'  : 'deusx', \n#     'userEmail' : 'deus_x@pobox.com', \n#     'fooPref'   : 'bar'}\n</code></pre>\n<p>There isn't any spectacular code behind all this, and the idea <em>was</em> Kimbro's, but it's working.  It's also incredibly convenient, especially with the little XML-to-dict extraction map method I whipped up.  This would take a bit more work to pry it out of its current context, such as turning the hardcoded namespaces into an option, among other things.  But, <a href=\"http://www.decafbad.com/cvs/*checkout*/dbagg3/lib/dbagg3/xmlutils.py\">here's the code</a> for you to peruse.</p>\n<p>(I got hooked early on subverting in-built language constructs from perl's <code>tie</code> facilities, and C++'s operator overloading.  Now I'm loving Python's <a href=\"http://diveintopython.org/object_oriented_framework/special_class_methods2.html\">special class methods</a>.  Someday, maybe, I'll actually get down to doing some work in LISP and wrap my head around some <em>real</em> language subversion.)</p>\n<p>Anyway, while this is neither quite <a href=\"http://dev2dev.bea.com/products/wlworkshop/articles/JSchneider_XML.jsp\">Native XML Scripting</a> nor XML as <a href=\"http://www.xmldatabases.org/WK/blog/663?t=item\">a native language construct</a>, it's getting there.</p>\n<div id=\"comments\" class=\"comments archived-comments\"><h3>Archived Comments</h3>\n<ul class=\"comments\">\n<li class=\"comment\" id=\"comment-221090556\">\n<div class=\"meta\">\n<div class=\"author\">\n<a class=\"avatar image\" rel=\"nofollow\" href=\"http://naeblis.cx\"><img src=\"http://www.gravatar.com/avatar.php?gravatar_id=abfc88b96ae18c85ba7aac3bded2ec5e&amp;size=32&amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png\" width=\"\" height=\"\"></a>\n<a class=\"avatar name\" rel=\"nofollow\" href=\"http://naeblis.cx\">Ryan Tomayko</a>\n</div>\n\n\n<p><a href=\"#comment-221090556\" class=\"permalink\"><time datetime=\"2004-09-01T17:29:27\">2004-09-01T17:29:27</time></a></p>\n</div>\n\n\n<div class=\"content\">Funny that. I also have one that has survived a couple of failed apps. I have a hard time dropping it to be honest and just keep lugging it around to each new project. \nhttp://naeblis.cx/cvs/percolator/xb/lib/xpdm.py?rev=HEAD&amp;content-type=text/vnd.viewcvs-markup\nIt has some pretty big issues. Among other things, creating nodes with namespace support is a little.. ermmm.. not there. But it does a lot of things well like garbage collecting xmlDoc instances (freeDoc), copying nodesets between documents, encoding things when they need to be, etc.\nAnyway, I wonder if maybe we all might benefit by teaming up on this and try to define what a complete xpathish wrapper atop libxml2 should look like. And really, why limit it to libxml2? I'm of the opinion that the value here is an interface that embraces xpath. The fact that it's running on top of the blazingly fast libxml2 is nice but coding against the XMLTRAMP like interface is the value for me.\nSo let me see if I can get some time together to whip up a quick comparison of the three implementations. I'll shoot that over to you and Kimbro and we can go from there. If these seem to work best as backyard APIs we like to keep close to us, we'll drop it. However, I think there's a good chance that we can all benefit by combining our efforts.</div>\n\n\n</li>\n</ul>\n\n\n</div>\n\n\n",
  "body": "So [Kimbro Staken][kimbro] posted this nifty idea to build [XPath based Python dictionaries][xpathdict] to access XML data as a part of his incredibly nifty [Syncato][syncato] microcontent management system.  Eventually, I've really got to break down and get that thing built and running on my server and my laptop-- it really seems like I'm reinventing so many wheels by not basing [`dbagg3`][dbagg3] on it.\r\n\r\nBut, while I'm in the process of wheel reinvention, how about I borrow Kimbro's idea?  I just threw together [a quick class called XPathDict][myxdict], based on [libxml2][libxml2].  It works a little something like this:\r\n\r\n    feed_xd = XPathDict(file=\"sample-atom.xml\")\r\n    for entry_node in feed_xd.nodes(\"//atom:entry\"):\r\n        entry = XPathDict(doc=entry_node.doc, node=entry_node)\r\n        print \"Title: \" % entry['atom:title']\r\n        if 'atom:author' in entry:\r\n            print \"Author: \" % entry['atom:author/atom:name']\r\n\r\n    xml = \"\"\"\r\n       <dbagg3:user xmlns=\"http://purl.org/atom/ns#\" \r\n                xmlns:dbagg3=\"http://decafbad.com/2004/07/dbagg3/\">\r\n            <name>deusx</name>\r\n            <email>deus_x@pobox.com</email>\r\n            <url>http://www.decafbad.com/</url>\r\n            <dbagg3:prefs>\r\n                <dbagg3:pref name=\"foo\">bar</dbagg3:pref>\r\n            </dbagg3:prefs>\r\n       </dbagg3:author>\r\n    \"\"\"\r\n\r\n    map = (\r\n        ('userName',  'a:name'),\r\n        ('userEmail', 'a:email'),\r\n        ('fooPref',   \"dbagg3:prefs/dbagg3:pref[@name='foo']\")\r\n    )\r\n\r\n    xd = XPathDict(xml=xml)\r\n    xd.cd(\"/dbagg3:user\")\r\n    print xd.extract(map)\r\n\r\n    #    {'userName'  : 'deusx', \r\n    #     'userEmail' : 'deus_x@pobox.com', \r\n    #     'fooPref'   : 'bar'}\r\n\r\nThere isn't any spectacular code behind all this, and the idea *was* Kimbro's, but it's working.  It's also incredibly convenient, especially with the little XML-to-dict extraction map method I whipped up.  This would take a bit more work to pry it out of its current context, such as turning the hardcoded namespaces into an option, among other things.  But, [here's the code][myxdict] for you to peruse.\r\n\r\n(I got hooked early on subverting in-built language constructs from perl's `tie` facilities, and C++'s operator overloading.  Now I'm loving Python's [special class methods][methods].  Someday, maybe, I'll actually get down to doing some work in LISP and wrap my head around some *real* language subversion.)\r\n\r\nAnyway, while this is neither quite [Native XML Scripting][nativexml] nor XML as [a native language construct][nativeconstruct], it's getting there.\r\n\r\n[methods]: http://diveintopython.org/object_oriented_framework/special_class_methods2.html\r\n[nativeconstruct]: http://www.xmldatabases.org/WK/blog/663?t=item\r\n[nativexml]: http://dev2dev.bea.com/products/wlworkshop/articles/JSchneider_XML.jsp\r\n[libxml2]: http://www.xmlsoft.org/\r\n[myxdict]: http://www.decafbad.com/cvs/*checkout*/dbagg3/lib/dbagg3/xmlutils.py\r\n[dbagg3]: http://www.decafbad.com/cvs/dbagg3/\r\n[syncato]: http://www.syncato.org/\r\n[kimbro]: http://www.xmldatabases.org/WK/blog\r\n[xpathdict]: http://www.xmldatabases.org/WK/blog/1964_XPath_based_Python_Dictionaries.item\r\n\r\n<div id=\"comments\" class=\"comments archived-comments\">\r\n            <h3>Archived Comments</h3>\r\n            \r\n        <ul class=\"comments\">\r\n            \r\n        <li class=\"comment\" id=\"comment-221090556\">\r\n            <div class=\"meta\">\r\n                <div class=\"author\">\r\n                    <a class=\"avatar image\" rel=\"nofollow\" \r\n                       href=\"http://naeblis.cx\"><img src=\"http://www.gravatar.com/avatar.php?gravatar_id=abfc88b96ae18c85ba7aac3bded2ec5e&amp;size=32&amp;default=http://mediacdn.disqus.com/1320279820/images/noavatar32.png\"/></a>\r\n                    <a class=\"avatar name\" rel=\"nofollow\" \r\n                       href=\"http://naeblis.cx\">Ryan Tomayko</a>\r\n                </div>\r\n                <a href=\"#comment-221090556\" class=\"permalink\"><time datetime=\"2004-09-01T17:29:27\">2004-09-01T17:29:27</time></a>\r\n            </div>\r\n            <div class=\"content\">Funny that. I also have one that has survived a couple of failed apps. I have a hard time dropping it to be honest and just keep lugging it around to each new project. \r\n\r\nhttp://naeblis.cx/cvs/percolator/xb/lib/xpdm.py?rev=HEAD&content-type=text/vnd.viewcvs-markup\r\n\r\nIt has some pretty big issues. Among other things, creating nodes with namespace support is a little.. ermmm.. not there. But it does a lot of things well like garbage collecting xmlDoc instances (freeDoc), copying nodesets between documents, encoding things when they need to be, etc.\r\n \r\nAnyway, I wonder if maybe we all might benefit by teaming up on this and try to define what a complete xpathish wrapper atop libxml2 should look like. And really, why limit it to libxml2? I'm of the opinion that the value here is an interface that embraces xpath. The fact that it's running on top of the blazingly fast libxml2 is nice but coding against the XMLTRAMP like interface is the value for me.\r\n\r\nSo let me see if I can get some time together to whip up a quick comparison of the three implementations. I'll shoot that over to you and Kimbro and we can go from there. If these seem to work best as backyard APIs we like to keep close to us, we'll drop it. However, I think there's a good chance that we can all benefit by combining our efforts.</div>\r\n            \r\n        </li>\r\n    \r\n        </ul>\r\n    \r\n        </div>\r\n    ",
  "parentPath": "./content/posts/archives/2004",
  "path": "2004/09/01/xpath-based-python-dictionaries-on-loan",
  "needsBuild": true,
  "prevPostPath": "2004/08/30/dbagg3-makingprogress",
  "prevPostTitle": "Making progress on dbagg3",
  "nextPostPath": "2004/09/12/moving-time-again",
  "nextPostTitle": "Moving time again"
}