<?xml version="1.0" encoding="UTF-8"?><feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xml:lang="en"
  >
  <id>http://livingcode.org/feed/atom</id>
  <updated>2009-11-13T19:33:25Z</updated>
  <title type="text">Living Code</title>
  <subtitle type="text">Programming for the Fun of It</subtitle>
  <link rel="self" type="application/atom+xml" href="http://livingcode.org/feed" />
  <link rel="alternate" href="http://livingcode.org" />
  <rights type="text">Copyright 2009</rights>
  <generator uri="http://wordpress.org/" version="2.8.6">WordPress</generator>
      <entry>
    <id>http://livingcode.org/2005/extending-nsbezierpath</id>
    <title type="html"><![CDATA[Extending NSBezierPath]]></title>
    <updated>2008-01-25T21:42:49Z</updated>
    <published>2005-01-29T21:36:43Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2005/01/29/extending-nsbezierpath/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2005/01/29/extending-nsbezierpath" />
    <category scheme="http://livingcode.org" term="Python" />
    <category scheme="http://livingcode.org" term="Tutorial" />
    <summary type="html"><![CDATA[Yesterday I wrote about how to extend NSImage so it can save to a file. Today we&#8217;ll tackle NSBezierPath. NSBezierPath is pretty cool for drawing, but it doesn&#8217;t support arbitrary regular polygons, just rects and ovals (and lines and arcs). And there&#8217;s not an easy way to extract the points that make up a path. [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2005/01/29/extending-nsbezierpath"><![CDATA[<p>Yesterday I wrote about how to extend NSImage so it can save to a file. Today we&#8217;ll tackle NSBezierPath. NSBezierPath is pretty cool for drawing, but it doesn&#8217;t support arbitrary regular polygons, just rects and ovals (and lines and arcs). And there&#8217;s not an easy way to extract the points that make up a path. And if you could extract the points, there isn&#8217;t a way to draw dots for the points instead of stroking or filling the path. OK, enough already, let&#8217;s look at some code.</p>
<p>First thing in the code, we&#8217;ll define some basic trigonometry routines to calculate the points for a polygon. Then we&#8217;ll create the class itself.</p>
<pre class="code">from objc import Category</pre>
<pre class="code">from AppKit import NSBezierPath</pre>
<pre class="code">import math</pre>
<pre class="code">
def poly_point(center, r, degrees):</pre>
<pre class="code">    x = r * math.cos(degrees) + center[0]</pre>
<pre class="code">    y = r * math.sin(degrees) + center[1]</pre>
<pre class="code">    return x,y</pre>
<pre class="code">def polypoints(center, r, numPoints, degreesRotation=0):</pre>
<pre class="code">    if numPoints &lt; 3:</pre>
<pre class="code">        raise ValueError, 'Must have at least 3 points in a polygon'</pre>
<pre class="code">    rotation = math.radians(degreesRotation)</pre>
<pre class="code">    theta = (math.pi * 2) / numPoints</pre>
<pre class="code">    return [poly_point(center, r, i*theta+rotation)</pre>
<pre class="code">        for i in range(numPoints)]</pre>
<pre class="code">class NSBezierPath(Category(NSBezierPath)):</pre>
<pre class="code">    def points(self):</pre>
<pre class="code">        points = []</pre>
<pre class="code">        for i in range(self.elementCount()):</pre>
<pre class="code">        elem, pts = self.elementAtIndex_associatedPoints_(i)</pre>
<pre class="code">        points += pts</pre>
<pre class="code">        return points</pre>
<pre class="code">
def appendBezierPathWithPolygonWithCenter_radius_numberOfPoints_(self, center, radius, numberOfPoints):</pre>
<pre class="code">	''' Creates a regular polygon '''</pre>
<pre class="code">	pts = polypoints(center, radius, numberOfPoints) self.moveToPoint_(pts[0])</pre>
<pre class="code">	for pt in pts[1:]:</pre>
<pre class="code">		self.lineToPoint_(pt)</pre>
<pre class="code">	self.closePath()</pre>
<pre class="code">
    def dot(self):</pre>
<pre class="code">        '''</pre>
<pre class="code">        Similar to stroke: and fill:, but draws dots for each point in the</pre>
<pre class="code">        path. Dot size is based on linewidth. Not as efficient, because it</pre>
<pre class="code">        creates a separate NSBezierPath each time it is called.</pre>
<pre class="code">        '''</pre>
<pre class="code">        tmp_path = NSBezierPath.alloc().init()</pre>
<pre class="code">        width = self.lineWidth()</pre>
<pre class="code">        offset = width / 2</pre>
<pre class="code">        for point in self.points():</pre>
<pre class="code">            rect = (point[0] - offset, point[1] - offset),(width, width)</pre>
<pre class="code">            tmp_path.appendBezierPathWithOvalInRect_(rect)</pre>
<pre class="code">        tmp_path.fill()</pre>
<p>OK, hopefully the above is reasonably clear. You can follow along with any calls which are unfamiliar by firing up AppKiDo or the Apple documentation for NSBezierPath. If you&#8217;re going to use the dot: method a lot you might want to cache the path so you&#8217;re not creating a new NSBezierPath every time, it depends on what you need.</p>
<p>Here&#8217;s a short script you can run on the command line to create a hexagon and demonstrate fill:, stroke: and dot:</p>
<pre><span class="code">from AppKit import NSApplication, NSBezierPath, NSColor, NSImage</span></pre>
<pre><span class="code">from Foundation import NSInsetRect, NSMakeRect</span></pre>
<pre><span class="code">import image_ext, bezier_path_ext</span></pre>
<pre></pre>
<pre><span class="code">app = NSApplication.sharedApplication()</span></pre>
<pre><span class="code">image = NSImage.alloc().initWithSize_((64,64))</span></pre>
<pre><span class="code">image.fillWithColor_(NSColor.clearColor())</span></pre>
<pre><span class="code">image.lockFocus()</span></pre>
<pre><span class="code">hex = NSBezierPath.alloc().init()</span></pre>
<pre><span class="code">hex.appendBezierPathWithPolygonWithCenter_radius_numberOfPoints_((32,32), 26, 6)</span></pre>
<pre><span class="code">NSColor.greenColor().set()</span></pre>
<pre><span class="code">hex.fill()</span></pre>
<pre><span class="code">hex.setLineWidth_(2)</span></pre>
<pre><span class="code">NSColor.blueColor().set()</span></pre>
<pre><span class="code">hex.stroke()</span></pre>
<pre><span class="code">hex.setLineWidth_(8)</span></pre>
<pre><span class="code">NSColor.redColor().set()</span></pre>
<pre><span class="code">hex.dot()</span></pre>
<pre><span class="code">image.unlockFocus()</span></pre>
<pre><span class="code">image.writeToFilePath_('hex.png')</span></pre>
<p>Which results in this:  <img src="http://livingcode.org/images/hex1.png" height="64" width="64" /></p>
<p>Why am I so interested in points and dots? Well, they let me visualize control points for arcs for one thing. Perhaps tomorrow we can explore more along those lines.</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2005/extending-nsimage</id>
    <title type="html"><![CDATA[Extending NSImage]]></title>
    <updated>2008-01-26T04:19:43Z</updated>
    <published>2005-01-26T06:25:58Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2005/01/25/extending-nsimage/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2005/01/25/extending-nsimage" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[I&#8217;m going to try to post smaller snippets and experiments, more frequently. I&#8217;ve been struggling with creating images in code for a game I&#8217;m working on and had some successes lately that I wanted to share. Along the way we get to play with Categories, which allow existing Cocoa classes to be extended with new [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2005/01/25/extending-nsimage"><![CDATA[<p>I&#8217;m going to try to post smaller snippets and experiments, more frequently. I&#8217;ve been struggling with creating images in code for a game I&#8217;m working on and had some successes lately that I wanted to share. Along the way we get to play with Categories, which allow existing Cocoa classes to be extended with new methods at runtime without access to the source code. Categories are in the latest release of PyObJC, but the example I&#8217;m giving uses a fresh checkout from the Subversion repository because I turned up a bug which Ronald Oussoren was kind enough to identify and immediately fix. Since this example is already on the bleeding edge, I&#8217;ll also dabble with Python2.4 descriptors.</p>
<p>The specific problem I was faced with is that it is easy enough to create images programmatically, or to read them in from a file, but there was no obvious way to save them to a file. A bit of googling led me to <a href="http://borkware.com/quickies/">Mark Dalrymple&#8217;s</a> quickies which has lots of tips and tricks for programming Cocoa in Objective-C and which I got the basics for writing to an image to a file from. I pythonified it and turned it into a method of NSImage through the magic of Categories, adding a bit more along the way.</p>
<pre class="code">image_ext.py</pre>
<pre class="code">from objc import Category</pre>
<pre class="code">from AppKit import *</pre>
<pre class="code">from os.path import splitext</pre>
<pre class="code">
_fileRepresentationMapping = { '.png': NSPNGFileType,</pre>
<pre class="code">                               '.gif': NSGIFFileType,</pre>
<pre class="code">                               '.jpg': NSJPEGFileType,</pre>
<pre class="code">                               '.jpeg': NSJPEGFileType,</pre>
<pre class="code">                               '.bmp': NSBMPFileType,</pre>
<pre class="code">                               '.tif': NSTIFFFileType,</pre>
<pre class="code">                               '.tiff': NSTIFFFileType, }</pre>
<pre class="code">
def _getFileRepresentationType(filepath):</pre>
<pre class="code">    base, ext = splitext(filepath)</pre>
<pre class="code">    return _fileRepresentationMapping[ext.lower()]</pre>
<pre class="code">class NSImage(Category(NSImage)):</pre>
<pre class="code"></pre>
<pre class="code">    def rect(self):</pre>
<pre class="code">        return (0,0),self.size()</pre>
<pre class="code"></pre>
<pre class="code">    # If you're using the current release of PyObjC and don't feel like grabbing the fix</pre>
<pre class="code">    # from the repository, remove this method altogether and read in from files as</pre>
<pre class="code">    # usual (reading isn't so tricky)</pre>
<pre class="code">    @classmethod # If you're using Python 2.3 comment this line and uncomment below</pre>
<pre class="code">    def imageWithFilePath_(cls, filepath):</pre>
<pre class="code">        return NSImage.alloc().initWithContentsOfFile_(filepath)</pre>
<pre class="code">    #imageWithFilePath_ = classmethod(imageWithFilePath_)</pre>
<pre class="code"></pre>
<pre class="code">    def writeToFilePath_(self, filepath):</pre>
<pre class="code">        self.lockFocus()</pre>
<pre class="code">        image_rep = NSBitmapImageRep.alloc().initWithFocusedViewRect_(self.rect())</pre>
<pre class="code">        self.unlockFocus()</pre>
<pre class="code">        representation = _getFileRepresentationType(filepath)</pre>
<pre class="code">        data = image_rep.representationUsingType_properties_(representation, None)</pre>
<pre class="code">        data.writeToFile_atomically_(filepath, False)</pre>
<pre class="code">
    def fillWithColor_(self, color):</pre>
<pre class="code">        self.lockFocus()</pre>
<pre class="code">        color.set()</pre>
<pre class="code">        NSBezierPath.fillRect_(self.rect())</pre>
<pre class="code">        self.unlockFocus()</pre>
<p>I probably should have just elided the <span class="code">imageWithFilePath:</span> method, since it is the only part which is really bleeding-edge, but I was so happy to get it working that I couldn&#8217;t bring myself to drop it. In any case, it&#8217;s the <span class="code">writeToFilePath:</span> method which I was looking for. In case its not obvious, this will grab the extension of the path you pass in and determine the right type of file to save. The key to saving images in Cocoa is that they have to pass through a subclass of NSImageRep and of NSData before they&#8217;re ready to write. This just encapsulates is all in one place.</p>
<p>While I was at it I added <span class="code">fillWithColor:</span> because I thought and image should be able to do that %-)</p>
<p>Next up: Teaching NSBezierPath new tricks.</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/oblique-strategies</id>
    <title type="html"><![CDATA[Oblique Strategies]]></title>
    <updated>2008-01-26T05:13:58Z</updated>
    <published>2004-11-25T05:02:43Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/24/oblique-strategies/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/24/oblique-strategies" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Today&#8217;s Example is a simple, but full application. Our setup file is getting more complicated as we give the app a custom icon and a name which isn&#8217;t taken from the main python file. We&#8217;re finally using the menus for more than just default behaviors. We&#8217;re loading in resources at runtime. We&#8217;re adding a custom [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/24/oblique-strategies"><![CDATA[<p>Today&#8217;s Example is a simple, but full application. Our setup file is getting more complicated as we give the app a custom icon and a name which isn&#8217;t taken from the main python file. We&#8217;re finally using the menus for more than just default behaviors. We&#8217;re loading in resources at runtime. We&#8217;re adding a custom About box. And we&#8217;re taking advantage of Python standard libraries from within a Cocoa program. One icon file + 224 lines of python, XML, and HTML.</p>
<p>Some years ago Brian Eno and Peter Schmidt created a deck of cards for brainstorming your way through artistic blocks. Each card had one idea, and they were called Oblique Strategies. The Whole Earth Review published a list of some of the strategies, the decks went through several editions, and there were quite a number of programs written to simulate drawing a card from the deck. The <a href="http://www.rtqe.net/ObliqueStrategies/">Oblique Strategies Web Site</a> has more details. You can buy the deck from <a href="http://www.enoshop.co.uk/">Brian Eno&#8217;s site</a>. And a group called curvedspace created a nice<a href="http://www.curvedspace.org/software/oblique.html"> OS X version</a> which you can download for free from their site.</p>
<p>The curvedspace app is so nice, in fact, that we&#8217;re going to slavishly imitate it. There are only a couple of problems with it. First, you can&#8217;t add your own quotes and sayings to the mix. Second, it&#8217;s free, but not open source, so you can&#8217;t patch it to allow you to add your own quotes. Tonight&#8217;s example will build a version identical to the curvedspace tool, but which allows you to choose from among several quote files, not just the Oblique Strategies. A future exercise will be to allow the user to customize it with new quotes from within the running application.</p>
<p>Since there&#8217;s quite a bit more code, and by reader request, this example is contained on a downloadable .dmg file. The file contains both the finished, runnable application, and all the source code. I&#8217;ll just be describing highlights of what&#8217;s different from earlier examples. You can download it all <a href="http://prdownloads.sourceforge.net/livingcode/ObliqueStrategies.dmg?download">here</a>.</p>
<p>What&#8217;s new? First of all, the <span class="code">setup.py</span> defines a plist resource inline to map some of the application features. This gives the application a name (&#8221;Oblique Strategies&#8221; rather than picking up &#8220;oblique&#8221; from the python file, and sets up some info for the About box. The setup call is a little more complex too, including English.lproj (which holds our icon) and Credits.html (which is the content of our About box), and passing in the plist we defined.</p>
<p>In the <span class="code">MainMenu.gsmarkup</span> we have added a bunch of menu items to the File menu, to allow the user to pick a quotation file. What&#8217;s interesting is that we&#8217;ve implemented &#8216;About Oblique Strategies&#8217; and Edit-&gt;Copy, but those menu items didn&#8217;t have to change.</p>
<p>In <span class="code">oblique.py</span>, the main script, we implement a subclass of NSWindow called TexturedWindow. This is to work around a limitation of the current version of Renaissance, which doesn&#8217;t support so-called Metal windows (because GNUstep doesn&#8217;t have them). Nicola has fixed this in CVS, so it will be in the next release, but in the meantime it is a simple class (4 lines of code) and we use the <span class="code">instanceOf</span> attribute of <span class="code">&lt;window /&gt;</span> to call our subclass in the <span class="code">MainWindow.gsmarkup</span>.</p>
<p>Our AppDelegate is similar to earlier examples, but has grown a couple of methods. The <span class="code">change()</span> method is called by our one button to select another quotation at random from the selected file (or a random file if you like). The <span class="code">chooseFile_(</span>) method checks to see which menu item called it, and based on the menu item, selects the file for future calls to <span class="code">change()</span>. There is one support function, <span class="code">getQuote(filename)</span> which uses Python standard file manipulation and the random module to pick a quote (much less verbose than doing this from Objective-C).</p>
<p>All that&#8217;s left are the quote files. These are simple text files with short quotations, one to a line. If a quote requires newlines, they can be embedded with &#8216;<span class="code">\n</span>&#8216;. The included files have quotes from Martin Fowler&#8217;s book &#8220;Refactoring,&#8221; the book &#8220;The Pragmatic Programmer,&#8221; the Magic 8-Ball, Jenny Holzer&#8217;s Truisms, and more. Enjoy!</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/housekeeping</id>
    <title type="html"><![CDATA[Housekeeping]]></title>
    <updated>2008-01-26T05:27:01Z</updated>
    <published>2004-11-11T05:23:42Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/10/housekeeping/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/10/housekeeping" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Various small improvements. Switched the template so code doesn&#8217;t run off the edge so easily. Fixed whitespace, which I forgot to do after switching the template (thanks, Xavier, for pointing that out!). All the code for the renaissance examples is available via cvs from the SourceForge Living Code project, in the somewhat predictable cvs module, [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/10/housekeeping"><![CDATA[<p>Various small improvements. Switched the template so code doesn&#8217;t run off the edge so easily. Fixed whitespace, which I forgot to do after switching the template (thanks, Xavier, for pointing that out!). All the code for the renaissance examples is available via cvs from the SourceForge <a href="http://sourceforge.net/projects/livingcode/">Living Code</a> project, in the somewhat predictable cvs module, <a href="http://cvs.sourceforge.net/viewcvs.py/livingcode/renaissance_examples/">renaissance_examples</a>. As some of the examples grow, I may only publish the highlights in the blog, and put the remainder in CVS. We&#8217;ll se how it goes.</p>
<p>Coming attractions. I&#8217;m researching how to build the Renaissance projects so they can be distributed (I haven&#8217;t forgotten you, Jorjun, I&#8217;m just still figuring it out myself). I can do it now (thanks, Bob!), but I want something more straightforward to build. Hopefully later tonight.</p>
<p>Now that we&#8217;ve got a brower for Renaissance files (see previous post), I wanted to create a markup file to show off most of the widgets and options, but realized there is no markup for tabbed views, so I&#8217;m going to try creating new tags from Python, and show how to do that. When I&#8217;ve got the tags which represent Cocoa widgets that do not yet have Renaissance representations working, then I&#8217;ll put together the demo gsmarkup file.</p>
<p>Then back to the Small Nerd examples and a couple of other applications (ports of existing tools, nothing terribly original yet).</p>
<p>It&#8217;s been nice to hear from people who are enjoying this series. If there are specific things you&#8217;d like to see, let me know, either in the comments, or at dethe(at)livingcode.org</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/a-new-renaissance</id>
    <title type="html"><![CDATA[A New Renaissance]]></title>
    <updated>2008-01-26T05:54:02Z</updated>
    <published>2004-11-04T05:49:54Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/11/03/a-new-renaissance/feed" thr:count="1"  />
    <link rel="alternate" href="http://livingcode.org/2004/11/03/a-new-renaissance" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[Yesterday I laid out the issues I have with using Interface Builder to create Cocoa applications (whether in Objective-C or Python), and my requirements for a replacement. To sum up, here are the requirements again:

Declarative
Simple and powerful
Able to replace NIB files and Interface Builder
Text-based, not binary
Agile for rapid development, adapts to rapidly changing code
Able to [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/11/03/a-new-renaissance"><![CDATA[<p>Yesterday I laid out the issues I have with using Interface Builder to create Cocoa applications (whether in Objective-C or Python), and my requirements for a replacement. To sum up, here are the requirements again:</p>
<ul>
<li>Declarative</li>
<li>Simple and powerful</li>
<li>Able to replace NIB files and Interface Builder</li>
<li>Text-based, not binary</li>
<li>Agile for rapid development, adapts to rapidly changing code</li>
<li>Able to specify simple apps completely, in code, without resorting to pictures or talking the user through mouse gestures</li>
</ul>
<p>As I hinted at previously, I think I&#8217;ve found the tool I was looking for in GNUstep Renaissance, and as an added bonus, it can be used to create applications for Linux, unix, and Windows using the GNUstep framework. So although I&#8217;m interested mainly in building applications for OS X, there is still a chance for cross-platform compatibility.</p>
<p>So what does Renaissance look like? It&#8217;s and XML format, similar to HTML and Mozilla XUL (but simpler than XUL). Today I will cover how to install Renaissance and set it up to use from PyObjC.</p>
<p>Prerequisites (this is my setup, others may work, but I haven&#8217;t tested them).</p>
<ol>
<li>A Mac</li>
<li>OS X (10.3)</li>
<li>PyObjC (1.1), available from <a href="http://pyobjc.sourceforge.net/">http://pyobjc.sourceforge.net/</a></li>
<li>py2app (0.1.4), available from <a href="http://pythonmac.org/wiki/py2app">http://pythonmac.org/wiki/py2app</a> (we&#8217;ll use this to build our double-clickable applications)</li>
<li>Renaissance framework (0.8), available from <a href="http://www.gnustep.it/Renaissance/Download.html">http://www.gnustep.it/Renaissance/Download.html</a> (this is the secret sauce)</li>
</ol>
<p>Once you have the prerequisites installed, you need to make Renaissance available from Python. In your site-packages directory (on my machine this is <em>/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site-packages</em>) add a Renaissance directory containing the following file:</p>
<p><strong>__init__.py </strong></p>
<pre class="code">import objc, AppKit, Foundation</pre>
<pre class="code">objc.loadBundle('Renaissance', globals(),</pre>
<pre class="code">    bundle_path='/Library/Frameworks/Renaissance.framework')</pre>
<pre class="code">del objc, AppKit, Foundation</pre>
<p>Well, that was easy enough. Next up, a Hello World application.</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/dom-back-to-xml-in-python</id>
    <title type="html"><![CDATA[DOM back to XML in Python]]></title>
    <updated>2008-01-26T06:15:36Z</updated>
    <published>2004-09-18T06:11:54Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/09/17/dom-back-to-xml-in-python/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/09/17/dom-back-to-xml-in-python" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[OK, time to crank up to speed, it&#8217;s been a lot longer than I intended between posts.
In the last episode we learned how to initialize many of the DOMs and DOM-like tools for Python from an XML document. Today we&#8217;re going to see how to convert these back to XML from the DOM. So fasten [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/09/17/dom-back-to-xml-in-python"><![CDATA[<p>OK, time to crank up to speed, it&#8217;s been a lot longer than I intended between posts.</p>
<p>In the last episode we learned how to initialize many of the DOMs and DOM-like tools for Python from an XML document. Today we&#8217;re going to see how to convert these back to XML from the DOM. So fasten your seatbelts and let&#8217;s go.</p>
<pre class="code">import domParse</pre>
<pre class="code">from xml.dom.ext.c14n import Canonicalize</pre>
<pre class="code">
def stringMinidom(filename):</pre>
<pre class="code">    return Canonicalize(domParse.parseMinidom(filename))</pre>
<pre class="code"></pre>
<pre class="code">def string4Dom(filename):</pre>
<pre class="code">    return Canonicalize(domParse.parse4Dom(filename))</pre>
<pre class="code"></pre>
<pre class="code">def stringDomlette(filename):</pre>
<pre class="code">    return Canonicalize(domParse.parseDomlette(filename))</pre>
<pre class="code"></pre>
<pre class="code">def stringLibXml(filename):</pre>
<pre class="code">    # pretty-printed, which may not be what you want,</pre>
<pre class="code">    # depending on the XML in question</pre>
<pre class="code">    return domParse.parseLibXml(filename).serialize(encoding='utf-8', format=True)</pre>
<pre class="code">    # 4DOM c14n breaks because libXML doesn't give you a DOM</pre>
<pre class="code">    # return Canonicalize(domParse.parseLibXml(filename))</pre>
<pre class="code"></pre>
<pre class="code">def stringPxDom(filename):</pre>
<pre class="code">    import pxdom</pre>
<pre class="code">    serializer = pxdom.LSSerializer()</pre>
<pre class="code">    return serializer.writeToString(domParse.parsePxDom(filename))</pre>
<pre class="code">    #return Canonicalize(domParse.parsePxDom(filename))</pre>
<pre class="code"></pre>
<pre class="code">def main(filename):</pre>
<pre class="code">    print '4DOM:', string4Dom(filename)</pre>
<pre class="code">    print 'Domlette:', stringDomlette(filename)</pre>
<pre class="code">    print 'MiniDom:', stringMinidom(filename)</pre>
<pre class="code">    print 'LibXml:', stringLibXml(filename)</pre>
<pre class="code">    print 'PxDom:', stringPxDom(filename)</pre>
<pre class="code">if __name__ == '__main__': main(domParse.small_filename)</pre>
<pre></pre>
<p>As you can see, there&#8217;s not much to it. This codes does require that you&#8217;ve installed the PyXML package, but if you&#8217;re serious about XML in Python, that will already be the case. In our next outing we can explore some of the less DOM-like, but more Pythonic ways to play with XML.</p>
<p>PyXML: <a href="http://pyxml.sourceforge.net/">http://pyxml.sourceforge.net/<br />
</a><br />
4Suite: <a href="http://4suite.org/index.xhtml ">http://4suite.org/index.xhtml </a></p>
<p>libxml: <a href="http://www.xmlsoft.org/">http://www.xmlsoft.org/</a> (instructions for the python bindings are linked from this page)</p>
<p>pxdom: <a href="http://www.doxdesk.com/software/py/pxdom.html ">http://www.doxdesk.com/software/py/pxdom.html </a></p>
<p>You may now return your trays to their upright positions.</p>
]]></content>
        </entry>
    <entry>
    <id>http://livingcode.org/2004/initializing-a-dom-in-python</id>
    <title type="html"><![CDATA[Initializing a DOM in Python]]></title>
    <updated>2004-09-16T06:15:38Z</updated>
    <published>2004-09-16T06:15:38Z</published>
    <author>
      <name>Dethe</name>
      <email>delza@livingcode.org</email>
<uri>http://livingcode.org/</uri>    </author>
    <link rel="replies" type="application/atom+xml" href="http://livingcode.org/2004/09/15/initializing-a-dom-in-python/feed" thr:count="0"  />
    <link rel="alternate" href="http://livingcode.org/2004/09/15/initializing-a-dom-in-python" />
    <category scheme="http://livingcode.org" term="Python" />
    <summary type="html"><![CDATA[There are many DOM options in Python, and I have trouble remembering how to load a document into the various DOMs. Here are a few common ones, although there are many variations on them (loading from URL or string, different configurations, etc.). This should provide a starting point.
# Examples for reading in various DOMs from [...]]]></summary>
      <content type="html" xml:base="http://livingcode.org/2004/09/15/initializing-a-dom-in-python"><![CDATA[<p>There are many DOM options in Python, and I have trouble remembering how to load a document into the various DOMs. Here are a few common ones, although there are many variations on them (loading from URL or string, different configurations, etc.). This should provide a starting point.</p>
<pre class="code"># Examples for reading in various DOMs from an XML file</pre>
<pre class="code"># MiniDOM</pre>
<pre class="code">def parseMinidom(filename):</pre>
<pre class="code">    try:</pre>
<pre class="code">        from xml.dom.minidom import parse</pre>
<pre class="code">        doc = parse(filename)</pre>
<pre class="code">        return doc</pre>
<pre class="code">    except Exception, e:</pre>
<pre class="code">        return 'parseMinidom() failed with exception %s' % e</pre>
<pre class="code"># 4DOM</pre>
<pre class="code">def parse4Dom(filename):</pre>
<pre class="code">    try:</pre>
<pre class="code">        from xml.dom.ext.reader.Sax2 import Reader</pre>
<pre class="code">        f = file(filename)</pre>
<pre class="code">        reader = Reader(validate=0, keepAllWs=0, catName=None)</pre>
<pre class="code">        doc = reader.fromStream(f) # slow!</pre>
<pre class="code">        f.close()</pre>
<pre class="code">        return doc</pre>
<pre class="code">    except Exception, e:</pre>
<pre class="code">        return 'parse4Dom() failed with exception %s' % e</pre>
<pre class="code"># Domlette</pre>
<pre class="code">def parseDomlette(filename):</pre>
<pre class="code">    try:</pre>
<pre class="code">        from Ft.Xml.Domlette import NonvalidatingReader as reader</pre>
<pre class="code">        f = file(filename)</pre>
<pre class="code">        uri = 'file:///%s' % filename # suppress warning</pre>
<pre class="code">        doc = reader.parseStream(f, uri)</pre>
<pre class="code">        f.close()</pre>
<pre class="code">        return doc</pre>
<pre class="code">    except Exception, e:</pre>
<pre class="code">        return 'parseDomlette() failed with exception %s' % e</pre>
<pre class="code"># libXml</pre>
<pre class="code">def parseLibXml(filename):</pre>
<pre class="code">    try:</pre>
<pre class="code">        import libxml2</pre>
<pre class="code">        f = file(filename)</pre>
<pre class="code">        data = f.read()</pre>
<pre class="code">        f.close()</pre>
<pre class="code">        doc = libxml2.parseDoc(data)</pre>
<pre class="code">        return doc</pre>
<pre class="code">    except Exception, e:</pre>
<pre class="code">        return 'parseLibXml() failed with exception %s' % e</pre>
<pre class="code"># pxDom</pre>
<pre class="code">def parsePxDom(filename):</pre>
<pre class="code">    try:</pre>
<pre class="code">        import pxdom</pre>
<pre class="code">        doc = pxdom.parse(filename)</pre>
<pre class="code">        return doc</pre>
<pre class="code">    except Exception, e:</pre>
<pre class="code">        return 'parsePxDom() failed with exception %s' % e</pre>
<pre class="code">def main():</pre>
<pre class="code">    import sys</pre>
<pre class="code">    filename = sys.argv[1]</pre>
<pre class="code">    print '4DOM:', parse4Dom(filename)</pre>
<pre class="code">    print 'Domlette:', parseDomlette(filename)</pre>
<pre class="code">    print 'MiniDom:', parseMinidom(filename)</pre>
<pre class="code">    print 'LibXml:', parseLibXml(filename)</pre>
<pre class="code">    print 'PxDom:', parsePxDom(filename)</pre>
<pre class="code">if __name__ == '__main__': main()</pre>
]]></content>
        </entry>
  </feed>
