WordPress Example

Consider the case where a family history site is being constructed based on WordPress. The family details are stored in a GEDCOM file and we would like to incorporate them into our site. Assume that a our site has the following structure:

There is nothing special about the directory structure, it is the one that I use on the Paloose servers and serves to isolate the various parts of the site. The relevant part of the GEDCOM (tree.ged) is (Frederick was a real person, my great-grandfather):

tree.ged
0 @I12@ INDI 1 NAME Frederick/FIELD-RICHARDS/ 2 GIVN Frederick 2 SURN FIELD-RICHARDS 1 TITL Rev 1 SEX M 1 OCCU Clergyman 1 BIRT 2 DATE 2 NOV 1846 2 PLAC Hackney,,,,, 1 BAPM 2 DATE 3 DEC 1865 1 CONF 2 DATE 8 DEC 1865 1 ORDN 2 DATE 21 DEC 1872 2 NOTE Deacon 1 ORDN 2 DATE 11 JUN 1876 2 NOTE Priest 1 DEAT 2 DATE 10 APR 1879 1 BURI 2 DATE 17 APR 1879 2 PLAC Hastings Borough Cemetery,,,,,T34 - Division D Section E. 1 FAMS @F78@ 1 FAMC @F81@ 1 REFN FrederickField-Richards 1 OBJE 2 FILE :images:FrederickField-Richards.jpg 3 FORM jpg 1 OBJE 2 FILE :images:Field-Richards-Crest.tif 3 FORM jpg

The GEDCOM generator in the sitemap translates this to a simple XML representation that is injected into the pipeline and can be processed by the XSL. The above scrap is transformed into the XML:

<g:indi id="@I12@"> <g:name data="Frederick/FIELD-RICHARDS/"/> <g:titl data="Rev"/> <g:sex data="M"/> <g:occu data="Clergyman"/> <g:birt> <g:date data="2 NOV 1846"/> <g:plac data="Hackney,,,,,"/> </g:birt> <g:bapm> <g:date data="3 DEC 1865"/> </g:bapm> <g:conf> <g:date data="8 DEC 1865"/> </g:conf> <g:ordn> <g:date data="21 DEC 1872"/> <g:note data="Deacon"> </g:note> </g:ordn> <g:ordn> <g:date data="11 JUN 1876"/> <g:note data="Priest"> </g:note> </g:ordn> <g:deat> <g:date data="10 APR 1879"/> </g:deat> <g:buri> <g:date data="17 APR 1879"/> <g:plac data="Hastings Borough Cemetery,,,,,T34 - Division D Section E."/> </g:buri> <g:fams ref="@F78@"/> <g:famc ref="@F81@"/> <g:refn data="FrederickField-Richards"/> <g:obje> <g:file data=":images:FrederickField-Richards.jpg"> <g:form data="jpg"/> </g:file> </g:obje> <g:obje> <g:file data=":images:Field-Richards-Crest.tif"> <g:form data="jpg"/> </g:file> </g:obje> </g:indi>

The requirement of the WordPress history site is to have a page for each member of the family with excerpts from the family GEDCOM data at the topm of the page. First we need a page template in a WordPress theme for the site. Assume that this page exists and the relevant links to the page exist via the Dashboard. The relevant temmplate file is

wp-content/themes/history/people.php
<?php /* Template Name: People */ ?> <?php get_header(); ?> <div id="content" class="widecolumn"> <div id="main"> <?php echo paloose( 'people.html', $_SERVER[ 'QUERY_STRING' ] ); ?> </div> <?php get_footer(); ?>

The URL to access this is http://[host name]/wordpress/history/people/?who=FrederickField-Richards. First of all the Paloose plugin settings for the site must be entered to tell Paloose where the relevant files are stored:

The full Paloose (rather than the compact version) is being used. The data that Paloose uses in history is defined as an absolute path. Since we are using the full version of Paloose we must make sure that the Logging system is set up. The configuration file would typically look like:

configs/Paloose.xml
<?xml version="1.0" encoding="ISO-8859-1"?> <configuration xmlns="http://logging.apache.org/log4php/" threshold="all" INFO="false"> <appender name="paloose" class="LoggerAppenderDailyFile"> <param name="datePattern" value="Ymd" /> <!-- Change this to suit local conditions, but make sure the right permissions are set for the logging folder (777) --> <param name="file" value="../history/logs/paloose_%s.log" /> <layout class="LoggerLayoutTTCC"> <param name="threadPrinting" value="true" /> <param name="categoryPrefixing" value="true" /> <param name="contextPrinting" value="true" /> <param name="microSecondsPrinting" value="false" /> </layout> </appender> <root> <level value="INFO" /> <appender_ref ref="paloose" /> </root> <logger name="Sitemap"> <level value="INFO"/> </logger> </configuration>

Obviously local conditions might change this. The log4php subsystem is stored at the same level as the Paloose system. However it does not have to be and both the latter and log4php can be stored in a more central location if required. If the compact version is used the logging system can be safely ignored.

The root sitemap is relatively simple, throwing all request to the content directory:

history/sitemap.xmap
<?xml version="1.0" encoding="UTF-8"?> <?oxygen RNGSchema="/Library/Schemas/rng/sitemap/paloose-sitemap-1.3.4.rng" type="xml"?> <?oxygen SCHSchema="/Library/Schemas/rng/sitemap/paloose-sitemap-1.3.4.rng"?> <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> <map:components> <map:generators default="file"> <map:generator name="file" src="resource://lib/generation/FileGenerator" cachable="no"/> <map:generator name="px" src="resource://lib/generation/PXTemplateGenerator" cachable="no"> <map:use-request-parameters>true</map:use-request-parameters> </map:generator> </map:generators> <map:transformers default="xslt"> <map:transformer name="xslt" src="resource://lib/transforming/TRAXTransformer" cachable="no"> <map:use-request-parameters>true</map:use-request-parameters> </map:transformer> <map:transformer name="log" src="resource://lib/transforming/LogTransformer"/> </map:transformers> <map:serializers default="xml"> <map:serializer name="xhtml" mime-type="text/html" src="resource://lib/serialization/XHTMLSerializer"> <doctype-public>-//W3C//DTD XHTML 1.0 Transitional//EN</doctype-public> <doctype-system>http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</doctype-system> <encoding>iso-8859-1</encoding> </map:serializer> <map:serializer name="xml" mime-type="text/xml" src="resource://lib/serialization/XMLSerializer"/> </map:serializers> <map:matchers default="wildcard"> <map:matcher name="wildcard" src="resource://lib/matching/WildcardURIMatcher"/> </map:matchers> </map:components> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- PIPELINES -*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <map:pipelines> <map:pipeline> <map:match pattern="**.html"> <map:mount src="cocoon://content/sitemap.xmap"/> </map:match> <map:handle-errors> <map:generate type="px" src="context://content/error.xml"/> <map:transform src="context://resources/transforms/buildMenus.xsl"/> <map:transform src="context://resources/transforms/page2xhtml.xsl"> <map:parameter name="page" value="error"/> </map:transform> <map:transform src="context://resources/transforms/stripNamespaces.xsl"/> <map:serialize type="xml"/> </map:handle-errors> </map:pipeline> </map:pipelines> </map:sitemap>

Errors in the pipelines are handled here and return a simply formatted error message. All html requests are sent to a subsitemap which is:

history/content/sitemap.xmap
<?xml version="1.0" encoding="UTF-8"?> <?oxygen RNGSchema="../../../Schemas/rng/sitemap-v06.rng" type="xml"?> <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> <map:components> <map:generators default="file"> <map:generator name="gedcom" src="resource://lib/generation/GedComGenerator" cachable="no"/> </map:generators> <map:transformers default="xslt"/> <map:serializers default="xml"/> <map:matchers default="wildcard"/> </map:components> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- PIPELINES -*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <map:pipelines> <map:pipeline> <map:match pattern="people.html"> <map:generate type="gedcom" src="context://content/data/tree.ged"/> <map:transform src="context://resources/transforms/person2xhtml.xsl"> <map:parameter name="who" value="{request-param:who}"/> </map:transform> <map:serialize type="xml"/> </map:match> </map:pipeline> </map:pipelines> </map:sitemap>

All very straightforward with the pipeline returning data based on the GEDCCOM data and the transform:

<?xml version="1.0"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:g="http://gedcom.org/dtd/gedxml55.dtd" version="1.0"> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <!-- Add any parameters from the sitemap here. --> <xsl:param name="who"/> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <!-- Add your global variables here as required. The default values are set here as well. --> <xsl:variable name="gWho" select="$who"/> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <xsl:template match="/"> <xsl:variable name="individualId" select="//g:refn[@data = $gWho]/parent::*[1]/@id"/> <xsl:variable name="birthDate" select="//g:indi[@id = $individualId]/g:birt/g:date/@data"/> <xsl:variable name="deathDate" select="//g:indi[@id = $individualId]/g:deat/g:date/@data"/> <xsl:variable name="title" select="//g:indi[@id = $individualId]/g:titl/@data"/> <xsl:variable name="name" select="//g:indi[@id = $individualId]/g:name/@data"/> <xsl:element name="div"> <xsl:attribute name="id">mainFrame</xsl:attribute> <xsl:element name="div"> <xsl:attribute name="class">personTitleTextPanel</xsl:attribute> <xsl:element name="div"> <xsl:attribute name="id">personName</xsl:attribute> <xsl:value-of select="$name"/> <xsl:if test="not( string-length( $title ) = 0 )"> <xsl:value-of select="concat( ' (', $title, ')' )"/> </xsl:if> </xsl:element> <xsl:element name="div"> <xsl:attribute name="id">personDates</xsl:attribute> <xsl:call-template name="common.outputBirthDeathDates"> <xsl:with-param name="inBirthDate" select="$birthDate"/> <xsl:with-param name="inDeathDate" select="$deathDate"/> </xsl:call-template> </xsl:element> </xsl:element> </xsl:element> </xsl:template> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <!-- -*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* --> <xsl:template name="common.outputBirthDeathDates"> <xsl:param name="inBirthDate"/> <xsl:param name="inDeathDate"/> <xsl:choose> <xsl:when test="string-length( $inBirthDate ) = 0 and string-length( $inDeathDate ) = 0"> <xsl:text> </xsl:text> </xsl:when> <xsl:when test="string-length( $inBirthDate ) = 0 "> <xsl:value-of select="concat( '(d.', $inDeathDate, ')' )"/> </xsl:when> <xsl:when test="string-length( $inDeathDate ) = 0 "> <xsl:value-of select="concat( '(b.', $inBirthDate, ')' )"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="concat( '(', $inBirthDate, ' – ', $inDeathDate, ')' )"/> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>

Obviously this is a highly simplistic example but the basic principle is common to most cases.

Copyright 2006 — 2011 Hugh Field-Richards. All Rights Reserved.