« March 2005 | Main | May 2005 »

April 21, 2005

Testing for the presence of objects in Zope

Here's a ZPT way to check for the presence of a particular folder in Zope:

<tal:block tal:define="
  folders python:context.objectValues('Folder');
" tal:repeat="folder python:folders">
<tal:block tal:define="
  this_id python:folder.getId();
  folder_name python:record['foaf_nick_name'];
" tal:condition="python:this_id == folder_name">
<tal:block tal:condition="python: root.new_site.contact.is_rstx_here(folder=folder,test_id='role_stx') == 1
">
<h3>Role and responsibilities</h3>
<tal:block tal:define="
  rstx python:modules['Products'].PythonScripts.standard.restructured_text;
  content_text python: folder.role_stx;
" tal:replace="structure python:rstx(content_text)"/>
</tal:block>
</tal:block>
</tal:block>

The following Python does the same but checks for rstx docs or DTML methods and is called as is_rstx_here() above:

for item in folder.objectValues('ReStructuredText Document'):
  this_id = item.getId()
  if this_id == str(test_id):
    return 1
for item in folder.objectValues('DTML Method'):
  this_id = item.getId()
  if this_id == str(test_id):
    return 1
return 0

Posted by pj at 04:31 PM

April 20, 2005

Contingent DIV blocks in ZPT - a design flaw.

I've got a problem with the design of ZPT. If I want a DIV block which starts in one iteration of a tal:repeat block but finishes a number of iterations later, then this can't be done, because the resulting code would give opening and closing tags out of document sequence breaking the template.

The only recourse seems to be to print the extra tagging as a a result of a tal:condition test.. YUUUCK:

<tal:block
tal:define="
global counter python:counter + 1;
global odd_even python:root.new_site.odd_or_even(test_figure=counter);
"
tal:condition="python: odd_even == 'odd'"
tal:replace="structure string:&lt;div class=&quot;row&quot;&gt;"/>

....Then the same for the closing block...

<tal:block tal:condition="python: odd_even == 'even'" tal:replace="structure string:&lt;/div&gt; <!-- End of row div -->"/>

Posted by pj at 04:13 PM

Changing the content type in page templates

<tal:block tal:define="
dummy python: container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/xml');
" tal:replace="structure string:&lt;?xml version=&quot;1.0&quot;?&gt;"/>

Posted by pj at 01:03 PM

Testing counters to see if they are odd or even

The following is a simple Python script to test whether a number is odd or even:

test_figure = float(test_figure)
half_of_it = float(test_figure/2)
#print str(half_of_it)
if int(half_of_it) == float(half_of_it):
  return 'even'
else: return 'odd'

It relies on the fact that casting a floating point number to an integer will round it up or down, and that dividing an odd number by two always gives a float, whereas dividing an even number gives an integer.

Posted by pj at 11:14 AM

April 18, 2005

Calling one page template inside another

Wow this is so much easier than calling DTML from within ZPT:

(In fact maybe you could do this with DTML too :~)

<tal:block tal:define="
dummy python: container.REQUEST.set('foaf_email', record['foaf_email']);
content_text root/new_site/contact/embedded_foafs;"
tal:replace="structure python: '<!--' + content_text + '-->'"/>

Note that I can pass it params in the REQUEST too..

Posted by pj at 03:48 PM

How to do RDF with Zope / ZPT

I've been trying to generate FOAF RDF from a Page Template. This has proven quite tricky. Zope 2.7 seems to stop wanting to parse and render the template if you change the content-type to text/xml from text/html.

This is not only a pain but is also intermittent.

The first thing I had to do therefore was re-set the content-type in the response header as follows, leaving the template content-type as text/html so the ZPT engine would parse it:

<tal:block tal:define="
dummy python: container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/xml');" />

Then I had to use tal:replace to put the XML declaration back in:

<tal:block tal:define="dummy python:
container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/xml');"
tal:replace="structure
string:&lt;?xml version=&quot;1.0&quot;?&gt;"/>

Because I wanted to use the same template for single FOAFs and multiples I had to test for a foaf_email parameter in the request. This is doable with has_key.

However, because tal:condition affects both subsequent tal:define statements and the rendering of any child nodes within the block where it is called, and scope of tal:define vars is limited to the current block, I've had to resort to passing variables up into the request namespace. This is due to the lack of a syntactic equivalent of <dtml-if>..<dtml-else>. This gives very obfuscatory code:

<tal:block tal:define="
request python: container.REQUEST;
email python: None;
where_clause string: where 1;
wc python: request.set('where_clause', where_clause);
">
<tal:block tal:condition="python:request.has_key('foaf_email')">
<tal:block tal:define="
email python: request['foaf_email'];
where_clause python:' where foaf_email=\'' + str(email) + '\'';
wc python: request.set('where_clause', where_clause);
"/>
</tal:block>
<rdf:RDF
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#"
xmlns:mofoaf="http://minnesota.ncl.ac.uk/mofoaf/1.0/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:dc="http://purl.org/dc/elements/1.1"
tal:define="
foaf_recs
python:root.generic_query(query_sql='select * from ltsn01_ng.01_foafs' + request['where_clause']);
work_url string:http://www.ltsn-01.ac.uk;
info_url_stem python: work_url + '/new_site/contact/person_details?foaf_id=';
">
.....RDF stuff here.....
</rdf:RDF>
</tal:block>

You'll see the where clause for the SQL is fished out of the request namespace.

The full template is here:

- 01_foafs.rdf.txt

Hmmm.. Seems if I'd read my own posts I could have done it with a PHP like global statement instead.


Posted by pj at 01:24 PM

April 15, 2005

New 'Back in Business' FOAF specification

FOAF Vocabulary Specification

Posted by pj at 11:24 AM

April 13, 2005

Identifying unique visitors to a website

A list and explanation of the ways Urchin software uses to determine unique visits. The only way to avoid proxy and cache issues is to use their bespoke JavaScript tracking approach:

Urchin Documentation - Visitor Identification Methods

Posted by pj at 08:40 PM

Merging multiple RSS feeds

Suzanne thought it would be a good idea if we could merge multiple news feeds from BIOME, HS&P and HEALTH-01 for our joint portal page.

Whilst unconvinced of the requirement for such a thing I have come up with the following:

- http://www.ltsn-01.ac.uk/static/merge_feeds.php

To get a text/xml view of it in your browser use:

- http://www.ltsn-01.ac.uk/static/merge_feeds.php?debug=1

The script is as follows:

- http://www.ltsn-01.ac.uk/static/merge_feeds.txt

Merging multiple RSS feeds into one involves de-duping based on link URLs in items and interleaving items so that they appear next to items of the same age in the final feed.

The script pulls our news feed and the feed from a blog we're hosting and represents them. In theory it can handle as many feeds as you want.

But why? I hear you ask.. Errm.. still not sure? Suzanne?

As a side effect of all this work, I was determined to get the feed to validate on http://feedvalidator.org.

It doesn't like my image references so those are gone from the feed, then it was a matter of getting the right content-type (application/rss+xml), stripping annoying Windows meta characters from the feed, making sure there are no duplicate URLs, and I've UTF-8 encoded the final output for good measure.

- http://www.ltsn-01.ac.uk/static/strip_ms_chars.txt

Basically all the problems we've had with the LOM XML stuff.

I've done this with the rest of our feeds too and they now validate.

Posted by pj at 04:58 PM

April 12, 2005

Why 1.0 is best..

XML.com: Why Choose RSS 1.0?

Posted by pj at 08:44 AM

Handling RSS 1.0 in PHP

PHP and XML: Parsing RSS 1.0

Posted by pj at 08:43 AM

April 11, 2005

RSS events to XHTML notes by Libby Miller

RSS, xhtml and XSLT

Posted by pj at 03:05 PM

April 09, 2005

Embedding RDF in XHTML the hard way

RDF in HTML: Approaches

Posted by pj at 05:27 PM

April 08, 2005

Meatspace metadata and authentication reminiscences

Super Springtime Dogtag Dignity contest results

Thanks for highlighting my lack of legal training Dr. P..

Posted by pj at 11:51 PM

A Python RDF parser

rdfxml.py: An RDF/XML Parser in under 10KB of Python

Posted by pj at 04:50 PM

The cult of Tony

We want a Labour party on May 6th. We just aren't inviting Tony:

Backing Blair :: UK General Election 2005

Take part in Operation Henman..

Print out a poster:

Poster - Blair


Posted by pj at 10:58 AM

April 07, 2005

Article about the UK Creative Commons effort

Policy DevCenter: Some Rights Reserved

Posted by pj at 07:50 PM

Doing dynamic reStructuredText in Zope

Suzanne and I have been playing with reStructuredText in Zope as a means of rapidly adding large chunks of copy to our new website. It is HWAYYY better than the old StructuredText.

The policy on the new site is that we are more carefully managing the URLs in page links and for the moment at least storing these as folder properties to be called in ZPT. This means for the navigation we only need to change URLs in one place.

We need to able to do the same in a simple way for links in rstx. This has its own way of handling URLs for links where they need only be defined once in the document to be re-used in lots of places.

We need a way to insert the values of properties into our rstx documents.

Fortunately in ZPT (which is where we are calling our rstx from) you have to define a rstx parser object and then pass text to it. This means that we could pass it the result of a DTML method and have the template still treat that text as rstx.

So instead of creating a reStructuredText document with the following:

.. _contact_us: /contact/contact_us

We create a DTML method with the following:

.. _contact_us: <dtml-with new_site><dtml-var contact_us_url></dtml-with>

So in our page template we now have the following to call the stx engine and the dtml:

<div style="text-align: justify;" id="content" tal:define="stx python:modules['Products'].PythonScripts.standard.restructured_text; content_text python:root.contact.index_html_dtml(root.contact);" tal:content="structure python:stx(content_text)"/>

Where this syntax: python:root.contact.index_html_dtml(root.contact) calls the DTML, passing its context as an argument.

Posted by pj at 11:12 AM

April 04, 2005

Paper detailing how to rig Zope / Plone up with Shibboleth authentication

MAMS - "Shibbolizing" Zope

Posted by pj at 08:56 PM

April 03, 2005

Datamining Apache Logs with PostgreSQL

ONLamp.com: Datamining Apache Logs with PostgreSQL

Datamining Apache Logs with PostgreSQL

Posted by pj at 09:15 PM