<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Code Train &#187; curl</title>
	<atom:link href="http://thecodetrain.co.uk/tag/curl/feed/" rel="self" type="application/rss+xml" />
	<link>http://thecodetrain.co.uk</link>
	<description>Where Neil Crosby talks about coding on the train...</description>
	<lastBuildDate>Wed, 18 Aug 2010 18:22:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Geolocation &amp; Beer: Part 4 &#8211; Finding the Beer</title>
		<link>http://thecodetrain.co.uk/2010/06/geolocation-and-beer-part-4-finding-the-beer/</link>
		<comments>http://thecodetrain.co.uk/2010/06/geolocation-and-beer-part-4-finding-the-beer/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 20:24:18 +0000</pubDate>
		<dc:creator>Neil Crosby</dc:creator>
				<category><![CDATA[Blog Posts]]></category>
		<category><![CDATA[apc]]></category>
		<category><![CDATA[beer]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[geolocation]]></category>

		<guid isPermaLink="false">http://thecodetrain.co.uk/?p=449</guid>
		<description><![CDATA[<p>Now, I know I said there were only going to be three parts to this series, but I&#8217;ve just realised that I missed out a quite important part of how I built <a href="http://beernear.me">Beer Near Me</a> &#8211; how I found the beer!</p>

<p>Even though Beer Near Me was only ever really built as a weekend project intended to help me learn about using the <code>navigator.geolocation</code> API, it was still pretty important to get some data to display on a map showing where the local beer was. After all, without that what would the point be?</p>

<h2>Gathering the Data</h2>

<p>To gather the local beer data I make several searches using the <a href="http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_local">Google Local Search API</a> &#8211; one that covers pubs, one for cocktail bars, one for off-licences, and so on.  The searches I make to Google&#8217;s local search look something a little like this:</p>

<pre><code>http://ajax.googleapis.com/ajax/services/search/local
    ?v=1.0
    sll={$sll}
    radius=1
    q={$thing}%20loc:{$sll}
    key={$apiKey}
</code></pre>

<p>Lets walk through those query string parameters…</p>

<ul>
<li><p><code>sll</code> doesn&#8217;t actually stand for anything according to the docs, but denotes the centre point of of the search you&#8217;d like to perform.  It&#8217;s a comma separated latitude/longitude value, so you&#8217;d use something like <code>52.2282962,0.1537945</code> for this parameter.</p></li>
<li><p><code>radius</code> is the radius around the centre point that you&#8217;d like to search within, in miles.</p></li>
<li><p><code>q</code> is the most important parameter by far though; being the query term for the thing you&#8217;re wanting to search for.  </p>

<p>You&#8217;ll notice that I&#8217;ve added a <code>loc:</code> onto the query.  It turns out that without this undocumented extra bit of data, Google really doesn&#8217;t return much from its local searches.  Before <a href="http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-3-static-maps/">last week&#8217;s post</a> I wasn&#8217;t using this extra qualifier, and whilst my searches were being centered around the expected point they weren&#8217;t returning much data. </p>

<p>A case in point was around The Bricklayers Arms. Without the <code>loc:</code> qualifier The Bricklayers Arms was nowhere to be found.  With the qualifier it suddenly started being returned by the searches to Google, along with a whole bunch of other local pubs.</p></li>
</ul>

<h2>Interpreting the Data</h2>

<p>So, if that&#8217;s the search we make, what does the data we get back look like?</p>

<pre><code>{
    "responseData": {
        "results": [
            {
                "GsearchResultClass":"GlocalSearch",
                "lat":"59.334743",
                "lng":"18.063034",
                "accuracy":"8",
                "title":"\u003cb\u003ePub\u003c/b\u003e",
                "titleNoFormatting":"Pub",
                "streetAddress":"Hötorget 13",
                "city":"Stockholm",
                "country":"Sweden",
                …
                "phoneNumbers":[
                    {"type":"","number":"08-782 19 30"},
                    {"type":"","number":"08-789 19 30"}
                ],
                "addressLines":[
                    "Hötorget 13",
                    "111 57 Stockholm, Sweden"
                ]
            },
            {
                // another result
            }
        ]
    }, 
    "responseDetails": null, 
    "responseStatus": 200
}
</code></pre>

<p>(The data above is, by necessity, just a snippet of what&#8217;s actually returned.)</p>

<p>You&#8217;ll notice first of all that each result we get has a <code>GsearchResultClass</code> of <code>GlocalSearch</code> set.  This allows easy checking of the data type returned.  For our searches, the result class will always be <code>GlocalSearch</code>, but other searches would return values for web searches, images searches and more.</p>

<p>Moving on to the data that actually interests us, each item has the expected <code>lat</code> and <code>lng</code> attributes, along with other useful smidgens of data such as <code>title</code>, <code>streetAddress</code> etc.  </p>

<p>Of particular note are the <code>title</code> and <code>titleNoFormatting</code> attributes.  You&#8217;ll notice that within the <code>title</code> field the word &#8220;pub&#8221; is encapsulated in encoded bold tags.  Two things to note here;  first, &#8220;pub&#8221; was the thing we searched for, so this gets emboldened in the standard display that Google would like to use for results (but we&#8217;re still provided <code>titleNoFormatting</code> if we&#8217;d like to have access to an unformatted string). Second, any formatting applied by google in its API results will be encoded in this way.  In Beer Near Me, I take the easy way out for the data I&#8217;m needing, and use <code>titleNoFormatting</code>.</p>

<p>Moving away from the data that comes from a single API request, lets take a quick look at what happens once we move into the world of performing lots of searches at once.  Since with Beer Near Me I&#8217;m making multiple calls to Google to gather beer related locations, there&#8217;s the pretty large possibility that more than one of the searches will return the same place within its results.  The deduping I do on Beer Near Me is very simple in this case &#8211; I simply keep track of the latitudes and longitudes of all the places that have been returned.  That way if any locations turn up in a position that&#8217;s already had data assigned it it I can ignore it.  It&#8217;s not perfect, but it does the job well enough.</p>

<h2>Caching the Data</h2>

<p>The last thing I want to briefly mention that I&#8217;m doing with the data is caching it using PHP&#8217;s <a href="http://php.net/apc">APC</a>.</p>

<p>This was the first time I&#8217;d attempted using APC on one of my own projects, so I had to install it on my Ubuntu based dev box.  I did that following <a href="http://www.debian-administration.org/articles/574">these instructions</a>.</p>

<p>The reason for using APC to cache the calls to Google&#8217;s Local Search is simple &#8211; network calls are expensive and slow.  With on average five calls to Local Search occurring on each page load on Beer Near Me you&#8217;d hope that they wouldn&#8217;t be having to go across network every single time.   So, I implemented a very simple cache check:</p>

<pre><code>$url = "http://ajax.google…q=somesearch"
$urlHash = md5($url);

// Try and pull the data from cache
$results = apc_fetch($urlHash);

// If we don't find the data in cache we'll have to make
// an expensive call across the network.
if (!$results) {
    // Get the data however you'd normally get it
    …
    $results = curl_exec($ch);

    // now store the data in APC
    apc_store(
        $urlHash, // Key to identify the cache by
        $results, // Data from our curl call to store 
        $ttl      // Seconds - how long we'll cache for
    );
}
</code></pre>

<p>As you can see above, I&#8217;m only using two APC methods &#8211; <code>apc_fetch</code> and <code>apc_store</code>.  Really, this is all you generally need for simple caching; one method for getting the data if it already exists, and one for storing it in the cache if you had to get the data from elsewhere.</p>

<p>With that in place, any further requests to that same location will be a lot faster, since we&#8217;ll have stored the results locally.  Result.  For Beer Near Me I can afford to be fairly aggressive with our caching, since for the most parts new pubs and cocktail bars won&#8217;t spring up over the course of a few minutes and become immediately available in Google&#8217;s search results.</p>

<h2>No more locations</h2>

<p>And that&#8217;s it.  As far as I&#8217;m concerned, that&#8217;s everything I&#8217;ve done so far on Beer Near Me.  It&#8217;s been a fun little weekend project, and whilst there&#8217;s more I&#8217;d like to do with it at some point, I think I&#8217;m going to leave it alone for a few weeks now.  After all, <a href="http://sciencehackday.com">Science HackDay</a> is in just over two weeks time, and no doubt I&#8217;ll get wonderfully caught up in something new for that.  Hopefully whatever I hack on will even be useful.</p>
<div style="display:block"><small><em><a href="http://neilcrosby.com">Neil Crosby</a> also blogs at about t-shirts at <a href="http://iwearcotton.com">I Wear Cotton</a>, writes <a href="http://thetenwordreview.com/users/workingwithme">Ten Word Reviews</a>, and uploads <a href="http://www.flickr.com/photos/thevoicewithin/">photos</a> to flickr.  You can follow a combined feed of posts at <a href="http://neilcrosby.com/">NeilCrosby.com</a>.</em></small></div>]]></description>
			<content:encoded><![CDATA[<p>Now, I know I said there were only going to be three parts to this series, but I&#8217;ve just realised that I missed out a quite important part of how I built <a href="http://beernear.me">Beer Near Me</a> &#8211; how I found the beer!</p>

<p>Even though Beer Near Me was only ever really built as a weekend project intended to help me learn about using the <code>navigator.geolocation</code> API, it was still pretty important to get some data to display on a map showing where the local beer was. After all, without that what would the point be?</p>

<h2>Gathering the Data</h2>

<p>To gather the local beer data I make several searches using the <a href="http://code.google.com/apis/ajaxsearch/documentation/reference.html#_fonje_local">Google Local Search API</a> &#8211; one that covers pubs, one for cocktail bars, one for off-licences, and so on.  The searches I make to Google&#8217;s local search look something a little like this:</p>

<pre><code>http://ajax.googleapis.com/ajax/services/search/local
    ?v=1.0
    sll={$sll}
    radius=1
    q={$thing}%20loc:{$sll}
    key={$apiKey}
</code></pre>

<p>Lets walk through those query string parameters…</p>

<ul>
<li><p><code>sll</code> doesn&#8217;t actually stand for anything according to the docs, but denotes the centre point of of the search you&#8217;d like to perform.  It&#8217;s a comma separated latitude/longitude value, so you&#8217;d use something like <code>52.2282962,0.1537945</code> for this parameter.</p></li>
<li><p><code>radius</code> is the radius around the centre point that you&#8217;d like to search within, in miles.</p></li>
<li><p><code>q</code> is the most important parameter by far though; being the query term for the thing you&#8217;re wanting to search for.  </p>

<p>You&#8217;ll notice that I&#8217;ve added a <code>loc:</code> onto the query.  It turns out that without this undocumented extra bit of data, Google really doesn&#8217;t return much from its local searches.  Before <a href="http://thecodetrain.co.uk/2010/05/geolocation-and-beer-part-3-static-maps/">last week&#8217;s post</a> I wasn&#8217;t using this extra qualifier, and whilst my searches were being centered around the expected point they weren&#8217;t returning much data. </p>

<p>A case in point was around The Bricklayers Arms. Without the <code>loc:</code> qualifier The Bricklayers Arms was nowhere to be found.  With the qualifier it suddenly started being returned by the searches to Google, along with a whole bunch of other local pubs.</p></li>
</ul>

<h2>Interpreting the Data</h2>

<p>So, if that&#8217;s the search we make, what does the data we get back look like?</p>

<pre><code>{
    "responseData": {
        "results": [
            {
                "GsearchResultClass":"GlocalSearch",
                "lat":"59.334743",
                "lng":"18.063034",
                "accuracy":"8",
                "title":"\u003cb\u003ePub\u003c/b\u003e",
                "titleNoFormatting":"Pub",
                "streetAddress":"Hötorget 13",
                "city":"Stockholm",
                "country":"Sweden",
                …
                "phoneNumbers":[
                    {"type":"","number":"08-782 19 30"},
                    {"type":"","number":"08-789 19 30"}
                ],
                "addressLines":[
                    "Hötorget 13",
                    "111 57 Stockholm, Sweden"
                ]
            },
            {
                // another result
            }
        ]
    }, 
    "responseDetails": null, 
    "responseStatus": 200
}
</code></pre>

<p>(The data above is, by necessity, just a snippet of what&#8217;s actually returned.)</p>

<p>You&#8217;ll notice first of all that each result we get has a <code>GsearchResultClass</code> of <code>GlocalSearch</code> set.  This allows easy checking of the data type returned.  For our searches, the result class will always be <code>GlocalSearch</code>, but other searches would return values for web searches, images searches and more.</p>

<p>Moving on to the data that actually interests us, each item has the expected <code>lat</code> and <code>lng</code> attributes, along with other useful smidgens of data such as <code>title</code>, <code>streetAddress</code> etc.  </p>

<p>Of particular note are the <code>title</code> and <code>titleNoFormatting</code> attributes.  You&#8217;ll notice that within the <code>title</code> field the word &#8220;pub&#8221; is encapsulated in encoded bold tags.  Two things to note here;  first, &#8220;pub&#8221; was the thing we searched for, so this gets emboldened in the standard display that Google would like to use for results (but we&#8217;re still provided <code>titleNoFormatting</code> if we&#8217;d like to have access to an unformatted string). Second, any formatting applied by google in its API results will be encoded in this way.  In Beer Near Me, I take the easy way out for the data I&#8217;m needing, and use <code>titleNoFormatting</code>.</p>

<p>Moving away from the data that comes from a single API request, lets take a quick look at what happens once we move into the world of performing lots of searches at once.  Since with Beer Near Me I&#8217;m making multiple calls to Google to gather beer related locations, there&#8217;s the pretty large possibility that more than one of the searches will return the same place within its results.  The deduping I do on Beer Near Me is very simple in this case &#8211; I simply keep track of the latitudes and longitudes of all the places that have been returned.  That way if any locations turn up in a position that&#8217;s already had data assigned it it I can ignore it.  It&#8217;s not perfect, but it does the job well enough.</p>

<h2>Caching the Data</h2>

<p>The last thing I want to briefly mention that I&#8217;m doing with the data is caching it using PHP&#8217;s <a href="http://php.net/apc">APC</a>.</p>

<p>This was the first time I&#8217;d attempted using APC on one of my own projects, so I had to install it on my Ubuntu based dev box.  I did that following <a href="http://www.debian-administration.org/articles/574">these instructions</a>.</p>

<p>The reason for using APC to cache the calls to Google&#8217;s Local Search is simple &#8211; network calls are expensive and slow.  With on average five calls to Local Search occurring on each page load on Beer Near Me you&#8217;d hope that they wouldn&#8217;t be having to go across network every single time.   So, I implemented a very simple cache check:</p>

<pre><code>$url = "http://ajax.google…q=somesearch"
$urlHash = md5($url);

// Try and pull the data from cache
$results = apc_fetch($urlHash);

// If we don't find the data in cache we'll have to make
// an expensive call across the network.
if (!$results) {
    // Get the data however you'd normally get it
    …
    $results = curl_exec($ch);

    // now store the data in APC
    apc_store(
        $urlHash, // Key to identify the cache by
        $results, // Data from our curl call to store 
        $ttl      // Seconds - how long we'll cache for
    );
}
</code></pre>

<p>As you can see above, I&#8217;m only using two APC methods &#8211; <code>apc_fetch</code> and <code>apc_store</code>.  Really, this is all you generally need for simple caching; one method for getting the data if it already exists, and one for storing it in the cache if you had to get the data from elsewhere.</p>

<p>With that in place, any further requests to that same location will be a lot faster, since we&#8217;ll have stored the results locally.  Result.  For Beer Near Me I can afford to be fairly aggressive with our caching, since for the most parts new pubs and cocktail bars won&#8217;t spring up over the course of a few minutes and become immediately available in Google&#8217;s search results.</p>

<h2>No more locations</h2>

<p>And that&#8217;s it.  As far as I&#8217;m concerned, that&#8217;s everything I&#8217;ve done so far on Beer Near Me.  It&#8217;s been a fun little weekend project, and whilst there&#8217;s more I&#8217;d like to do with it at some point, I think I&#8217;m going to leave it alone for a few weeks now.  After all, <a href="http://sciencehackday.com">Science HackDay</a> is in just over two weeks time, and no doubt I&#8217;ll get wonderfully caught up in something new for that.  Hopefully whatever I hack on will even be useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodetrain.co.uk/2010/06/geolocation-and-beer-part-4-finding-the-beer/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Getting the CSS Validator running as a website</title>
		<link>http://thecodetrain.co.uk/2009/03/getting-the-css-validator-running-as-a-website/</link>
		<comments>http://thecodetrain.co.uk/2009/03/getting-the-css-validator-running-as-a-website/#comments</comments>
		<pubDate>Mon, 09 Mar 2009 10:48:57 +0000</pubDate>
		<dc:creator>Neil Crosby</dc:creator>
				<category><![CDATA[Blog Posts]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[feci]]></category>
		<category><![CDATA[jigsaw]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tomcat]]></category>
		<category><![CDATA[validator]]></category>
		<category><![CDATA[w3c]]></category>
		<category><![CDATA[web-server]]></category>

		<guid isPermaLink="false">http://thecodetrain.co.uk/?p=222</guid>
		<description><![CDATA[<p>A week or so I wrote about <a href="http://thecodetrain.co.uk/2009/02/running-the-w3c-css-validator-locally-from-the-command-line/">running the W3C CSS Validator on the command-line</a>.  Yes, I know I said I didn&#8217;t need to run it as a website, but as it turns out the command-line version doesn&#8217;t seem to want to validate local files — only files being served from a  web-server.</p>

<p>So, I went back to scratch and tried installing it on a web-server.  Since my normal stack is Apache, MySQL and PHP I didn&#8217;t have any of the Java-based web-servers suggested by the W3C.  My first attempt at getting the validator working was to use <a href="http://www.w3.org/Jigsaw/">Jigsaw</a> &#8211; the same web-server as the W3C uses to run their version on.  Unfortunately, it didn&#8217;t work for me.  Bugger.</p>

<p>So, I tried <a href="http://tomcat.apache.org/">Tomcat</a>.  After following <a href="http://wiki.apache.org/tomcat/TomcatOnMacOS#head-3bfa4851688758d9bd07a188d4f552806af8b30f">Basil Bourque&#8217;s instructions</a> on <a href="http://wiki.apache.org/tomcat">Apache&#8217;s Tomcat wiki pages</a>, I got Tomcat working.  I then followed the rest of the <a href="http://jigsaw.w3.org/css-validator/DOWNLOAD.html">CSS Validator installation instructions</a> for Tomcat, and the validator worked in my browser.  Excellent.</p>

<p>There was a fly in the ointment though.  Whilst the validator worked in my browser, the same could not be said of my attempts to get it working via cURL calls from PHP using POST data.  I was using the same code as I&#8217;d used to validate against the W3C&#8217;s HTML validator, so I knew that I was able to successfully push POST data across to servers.  If I tried using GET requests to send the data to my local validator, then that worked. I verified the same thing was happening on the live CSS validator to make sure the problem wasn&#8217;t with my installation.  I know you&#8217;re thinking &#8220;well, if GET worked, why not just make requests that way?&#8221;  Unfortunately, I know that later I&#8217;ll be asking to validate much larger CSS rulesets — ones that will be far too large to fit on a URL.  So, I needed to use POST.</p>

<p>After a fair bit of poking, I realised that the in-browser version of the CSS Validator was setting an <code>enc</code> attribute value of <code>multipart/form-data</code> on the form when it was uploading files or sending textual data.  Conversely, it turns out that PHP was sending <code>application/x-www-form-urlencoded</code> as the encoding type instead, and the W3C CSS Validator just isn&#8217;t set up to accept that.  After a long time of trying to work out how to send things in <code>multipart/form-data</code> format using PHP&#8217;s cURL functions, I happened upon <a href="http://us2.php.net/manual/en/function.curl-setopt.php#84916">a comment on PHP&#8217;s curl_setopt function</a> which told me that if I gave PHP an array instead of a string it would automagically start using <code>multipart/form-data</code>.  As if by magic, my problem was solved.</p>

<p>My problems setting up my programmatic connection to the CSS Validator could easily have been solved by clearer documentation.  Nowhere that I could find in the Validator&#8217;s documentation was there any mention of needing to make POST requests using <code>multipart/form-data</code>.  If this had been stated somewhere I would at least I have known the path I needed to be looking down.  Likewise, lack of anything other than user-generated documentation for the PHP <code>CURLOPT_POSTFIELDS</code> cURL option made life far more difficult than it should have been.</p>

<p>Still, in the end I have a local version of the W3C&#8217;s CSS validator running on my laptop, and I&#8217;m able to connect to it programmatically to run tests.  Which is nice.</p>
<div style="display:block"><small><em><a href="http://neilcrosby.com">Neil Crosby</a> also blogs at about t-shirts at <a href="http://iwearcotton.com">I Wear Cotton</a>, writes <a href="http://thetenwordreview.com/users/workingwithme">Ten Word Reviews</a>, and uploads <a href="http://www.flickr.com/photos/thevoicewithin/">photos</a> to flickr.  You can follow a combined feed of posts at <a href="http://neilcrosby.com/">NeilCrosby.com</a>.</em></small></div>]]></description>
			<content:encoded><![CDATA[<p>A week or so I wrote about <a href="http://thecodetrain.co.uk/2009/02/running-the-w3c-css-validator-locally-from-the-command-line/">running the W3C CSS Validator on the command-line</a>.  Yes, I know I said I didn&#8217;t need to run it as a website, but as it turns out the command-line version doesn&#8217;t seem to want to validate local files — only files being served from a  web-server.</p>

<p>So, I went back to scratch and tried installing it on a web-server.  Since my normal stack is Apache, MySQL and PHP I didn&#8217;t have any of the Java-based web-servers suggested by the W3C.  My first attempt at getting the validator working was to use <a href="http://www.w3.org/Jigsaw/">Jigsaw</a> &#8211; the same web-server as the W3C uses to run their version on.  Unfortunately, it didn&#8217;t work for me.  Bugger.</p>

<p>So, I tried <a href="http://tomcat.apache.org/">Tomcat</a>.  After following <a href="http://wiki.apache.org/tomcat/TomcatOnMacOS#head-3bfa4851688758d9bd07a188d4f552806af8b30f">Basil Bourque&#8217;s instructions</a> on <a href="http://wiki.apache.org/tomcat">Apache&#8217;s Tomcat wiki pages</a>, I got Tomcat working.  I then followed the rest of the <a href="http://jigsaw.w3.org/css-validator/DOWNLOAD.html">CSS Validator installation instructions</a> for Tomcat, and the validator worked in my browser.  Excellent.</p>

<p>There was a fly in the ointment though.  Whilst the validator worked in my browser, the same could not be said of my attempts to get it working via cURL calls from PHP using POST data.  I was using the same code as I&#8217;d used to validate against the W3C&#8217;s HTML validator, so I knew that I was able to successfully push POST data across to servers.  If I tried using GET requests to send the data to my local validator, then that worked. I verified the same thing was happening on the live CSS validator to make sure the problem wasn&#8217;t with my installation.  I know you&#8217;re thinking &#8220;well, if GET worked, why not just make requests that way?&#8221;  Unfortunately, I know that later I&#8217;ll be asking to validate much larger CSS rulesets — ones that will be far too large to fit on a URL.  So, I needed to use POST.</p>

<p>After a fair bit of poking, I realised that the in-browser version of the CSS Validator was setting an <code>enc</code> attribute value of <code>multipart/form-data</code> on the form when it was uploading files or sending textual data.  Conversely, it turns out that PHP was sending <code>application/x-www-form-urlencoded</code> as the encoding type instead, and the W3C CSS Validator just isn&#8217;t set up to accept that.  After a long time of trying to work out how to send things in <code>multipart/form-data</code> format using PHP&#8217;s cURL functions, I happened upon <a href="http://us2.php.net/manual/en/function.curl-setopt.php#84916">a comment on PHP&#8217;s curl_setopt function</a> which told me that if I gave PHP an array instead of a string it would automagically start using <code>multipart/form-data</code>.  As if by magic, my problem was solved.</p>

<p>My problems setting up my programmatic connection to the CSS Validator could easily have been solved by clearer documentation.  Nowhere that I could find in the Validator&#8217;s documentation was there any mention of needing to make POST requests using <code>multipart/form-data</code>.  If this had been stated somewhere I would at least I have known the path I needed to be looking down.  Likewise, lack of anything other than user-generated documentation for the PHP <code>CURLOPT_POSTFIELDS</code> cURL option made life far more difficult than it should have been.</p>

<p>Still, in the end I have a local version of the W3C&#8217;s CSS validator running on my laptop, and I&#8217;m able to connect to it programmatically to run tests.  Which is nice.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodetrain.co.uk/2009/03/getting-the-css-validator-running-as-a-website/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WikiSlurp: Slurping Data from Wikipedia for Fun and Profit</title>
		<link>http://thecodetrain.co.uk/2008/09/wikislurp-slurping-data-from-wikipedia-for-fun-and-profit/</link>
		<comments>http://thecodetrain.co.uk/2008/09/wikislurp-slurping-data-from-wikipedia-for-fun-and-profit/#comments</comments>
		<pubDate>Sun, 28 Sep 2008 14:00:29 +0000</pubDate>
		<dc:creator>Neil Crosby</dc:creator>
				<category><![CDATA[Blog Posts]]></category>
		<category><![CDATA[barcamp]]></category>
		<category><![CDATA[barcamplondon5]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[isneilannoyedby]]></category>
		<category><![CDATA[mediawiki]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[scratching an itch]]></category>
		<category><![CDATA[thetenwordreview]]></category>
		<category><![CDATA[wikipedia]]></category>
		<category><![CDATA[wikislurp]]></category>

		<guid isPermaLink="false">http://thecodetrain.co.uk/?p=15</guid>
		<description><![CDATA[<p>This last weekend I attended <a href="http://barcamp.org/BarCampLondon5">BarCamp London 5</a>, where I talked about WikiSlurp, my technique for accessing the wealth of data held within Wikipedia.  I currently use WikiSlurp on both <a href="http://isneilannoyedby.com">Is Neil Annoyed By</a> and <a href="http://thetenwordreview.com">The Ten Word Review</a> as a way to pull in additional information about the things described on individual pages.</p>

<p>These are the slides I put together for my talk:</p>

<div style="width:425px;text-align:left" id="__ss_622769"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/neilcrosby/mining-wikipedia-for-awesome-data-presentation?type=powerpoint" title="Mining Wikipedia For Awesome Data">Mining Wikipedia For Awesome Data</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=mining-wikipedia-for-awesome-data-1222603282334492-9&#038;stripped_title=mining-wikipedia-for-awesome-data-presentation" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=mining-wikipedia-for-awesome-data-1222603282334492-9&#038;stripped_title=mining-wikipedia-for-awesome-data-presentation" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View SlideShare <a style="text-decoration:underline;" href="http://www.slideshare.net/neilcrosby/mining-wikipedia-for-awesome-data-presentation?type=powerpoint" title="View Mining Wikipedia For Awesome Data on SlideShare">presentation</a> or <a style="text-decoration:underline;" href="http://www.slideshare.net/upload?type=powerpoint">Upload</a> your own. (tags: <a style="text-decoration:underline;" href="http://slideshare.net/tag/wikislurp">wikislurp</a> <a style="text-decoration:underline;" href="http://slideshare.net/tag/wikipedia">wikipedia</a>)</div></div>

<p>If you just want to <a href="http://thecodetrain.co.uk/downloads/wikislurp-0.1.zip">download the Code</a>, go right ahead.  If you want to know more about the project, read the <a href="http://thecodetrain.co.uk/code/wikislurp/">WikiSlurp Project page</a>.</p>
<div style="display:block"><small><em><a href="http://neilcrosby.com">Neil Crosby</a> also blogs at about t-shirts at <a href="http://iwearcotton.com">I Wear Cotton</a>, writes <a href="http://thetenwordreview.com/users/workingwithme">Ten Word Reviews</a>, and uploads <a href="http://www.flickr.com/photos/thevoicewithin/">photos</a> to flickr.  You can follow a combined feed of posts at <a href="http://neilcrosby.com/">NeilCrosby.com</a>.</em></small></div>]]></description>
			<content:encoded><![CDATA[<p>This last weekend I attended <a href="http://barcamp.org/BarCampLondon5">BarCamp London 5</a>, where I talked about WikiSlurp, my technique for accessing the wealth of data held within Wikipedia.  I currently use WikiSlurp on both <a href="http://isneilannoyedby.com">Is Neil Annoyed By</a> and <a href="http://thetenwordreview.com">The Ten Word Review</a> as a way to pull in additional information about the things described on individual pages.</p>

<p>These are the slides I put together for my talk:</p>

<div style="width:425px;text-align:left" id="__ss_622769"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/neilcrosby/mining-wikipedia-for-awesome-data-presentation?type=powerpoint" title="Mining Wikipedia For Awesome Data">Mining Wikipedia For Awesome Data</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=mining-wikipedia-for-awesome-data-1222603282334492-9&#038;stripped_title=mining-wikipedia-for-awesome-data-presentation" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=mining-wikipedia-for-awesome-data-1222603282334492-9&#038;stripped_title=mining-wikipedia-for-awesome-data-presentation" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object><div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View SlideShare <a style="text-decoration:underline;" href="http://www.slideshare.net/neilcrosby/mining-wikipedia-for-awesome-data-presentation?type=powerpoint" title="View Mining Wikipedia For Awesome Data on SlideShare">presentation</a> or <a style="text-decoration:underline;" href="http://www.slideshare.net/upload?type=powerpoint">Upload</a> your own. (tags: <a style="text-decoration:underline;" href="http://slideshare.net/tag/wikislurp">wikislurp</a> <a style="text-decoration:underline;" href="http://slideshare.net/tag/wikipedia">wikipedia</a>)</div></div>

<p>If you just want to <a href="http://thecodetrain.co.uk/downloads/wikislurp-0.1.zip">download the Code</a>, go right ahead.  If you want to know more about the project, read the <a href="http://thecodetrain.co.uk/code/wikislurp/">WikiSlurp Project page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://thecodetrain.co.uk/2008/09/wikislurp-slurping-data-from-wikipedia-for-fun-and-profit/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
