Geonetwork v2.0.3 shema/template Howto
This How-to applies to: 2.0.3
Before you even start thinking about creating a new schema/template for geonetwork, I strongly suggest you to read all of the tutorial about XML, Xpath, XSL and XSD on w3schools.com
xml :
http://www.w3schools.com/xml/default.asp
xpath : http://www.w3schools.com/xpath/xpath_syntax.asp
xsl : http://www.w3schools.com/xsl/xsl_languages.asp
xsd : http://www.w3schools.com/schema/default.asp
Otherwise,
you will probably get confused and never
be able to fully understand what you’re doing.
- section 1 - General structure
- section 2 - Language specific tags
- section 3 - XSD creation
- section 4 - Geonetwork's specific stylesheet files
- section 5 - Geonetwork’s searching stylesheet
- section 6 - Your own Schema’s Stylesheet
- section 7 - Modifying geonetwork’s config files
- section 8 - Database integration
- section 9 - Testing
Geonetwork’s schema’s are the root element of all stored metadata. Based on a schema, the user can then create his custom templates. Schema uses a combination of XML technologies to store, edit and display metadata. This dynamic way to store and to show metadata makes it very flexible and, most of all, it will be compatible with any new future devices like blackberries, iphone, cellphones, etc.
1 – General structure : organisation_template.xml
Create a folder named exactly like your template name « organisation » in [geonet_root]/web/xml/schemas/ Here you will store various files mandatory to any geonetwork schema.
Start by thinking and writing down the XML structure of the metadata you would like to show with your schema. Let say I want to add a schema that let geonetwork users enter information about any organisation. The basic XML would look like this.
*Note that any metadata file that is published in geonetwork MUST have a unique universal id (UUID). The schema you’re creating will need one, since geonetwork considers schema as an other metadata. To get one, you can visit the International Telecommunication Union at : http://www.itu.int/ITU-T/asn1/cgi-bin/uuid_generate
*Note that according to the w3c standard, all xml files must start with <?xml version="1.0" encoding="UTF-8"?>. Since this file will be place in the database and rearranged by the geonetwork’s api implementation, there is no need for the xml version declaration. Geonetwork will add the appropriate xml version declaration when needed.
<metadata>
<orgTitle>New organisation</orgTitle>
<orgAcronym/>
<orgParentInstitution/>
<orgDesc/>
<orgSuppInfo/>
<orgContactus>
<orgAddress/>
<orgPOBox/>
<orgCity/>
<orgPostalcode/>
<orgProvince/>
<orgCountry/>
<orgPhone/>
<orgFax/>
<orgWebsite/>
<orgEmail/>
</orgContactus>
<orgContactInfo>
<orgContactName/>
<orgContactRole/>
<orgContactEmail/>
<orgContactPhone/>
</orgContactInfo>
<mdFileID/>
</metadata>
Save this file as “organisation_template.xml”… you’ll need it later.
Note that what’s written in your template tag <orgTitle> will be displayed in the dropdown list of available templates when user creates new metadata.
2 – Language specific tags : /web/loc/[lang]/xml/organisation.xml
Now, create the file “organisation.xml” that will be placed in “[geonetwork_root_path]/web/loc/en/xml/”. This file will used to display each metadata header and help information in different languages. So create as many “organisation.xml” in the various localizations your geonetwork interface is available in. Following the example above, it will look like this:
*Note that the “help=” attribute is not always present. This is a personal decision, since most of the fields are self explanatory. However, all fields should be explained.
<?xml
version="1.0" encoding="UTF-8"?>
<root>
<metadata help="root entity which
defines metadata
about the organisation">Organisation's
Metadata</metadata>
<orgTitle help="The organisation's
name">Organisation's name</orgTitle>
<orgAcronym help="abbreviations that is
formed using
the initial letters of words or word parts in a name.">Acronym</orgAcronym>
<orgParentInstitution help="The institution above
this
organisation, if applicable">Parent
institution</orgParentInstitution>
<orgDesc help="Description of the
main goal of
the organisation">Description</orgDesc>
<orgContactus>Contact
us</orgContactus>
<orgAddress>Address</orgAddress>
<orgPOBox>P.O.
Box</orgPOBox>
<orgCity>City</orgCity>
<orgPostalcode>Postal
Code / Zip</orgPostalcode>
<orgProvince>Province
/ State</orgProvince>
<orgCountry>Country</orgCountry>
<orgPhone>Phone</orgPhone>
<orgFax>Fax</orgFax>
<orgWebsite>Website
http://</orgWebsite>
<orgEmail>Email</orgEmail>
<orgSuppInfo help="any other descriptive
information
about the dataset">Supplemental
Information</orgSuppInfo>
<orgContactInfo help="person to contact">Contact name</orgContactInfo>
<orgContactName>Name</orgContactName>
<orgContactRole>Position</orgContactRole>
<orgContactEmail>Email</orgContactEmail>
<orgContactPhone>Phone
and ext.</orgContactPhone>
<mdFileID help="unique identifier for
this
metadata file">File identifier</mdFileID>
</root>
***I strongly suggest to write the “help=” attribute right now. If you don’t, you will most likely never do it.
3- XSD creation : /web/xml/schemas/organisation/schema.xsd
XSD stands for XML Schema Definition. You will now tell geonetwork how your xml is organized. This is also where you will tell your geonetwork’s api implementation if some element are optional, mandatory, unique or if multiple instance of them car be created. For an exhaustive list of options, visit : http://www.w3schools.com/schema/el_element.asp
<?xml
version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<!-- complex
type declaration -->
<xs:element name="metadata" type="metadata"/>
<xs:complexType name="metadata">
<xs:sequence>
<xs:element ref="orgTitle"/>
<xs:element ref="orgAcronym"/>
<xs:element ref="orgParentInstitution"/>
<xs:element ref="orgDesc"/>
<xs:element ref="orgSuppInfo"/>
<xs:element ref="orgContactus"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="orgContactInfo" />
<xs:element ref="mdFileID"/>
</xs:sequence>
</xs:complexType>
<xs:element name="orgContactInfo" type="orgContactInfo" />
<xs:complexType name="orgContactInfo">
<xs:sequence>
<xs:element ref="orgContactName"/>
<xs:element ref="orgContactRole"/>
<xs:element ref="orgContactEmail"/>
<xs:element ref="orgContactPhone"/>
</xs:sequence>
</xs:complexType>
<xs:element name="orgContactus" type="orgContactus"/>
<xs:complexType name="orgContactus">
<xs:sequence>
<xs:element ref="orgAddress"/>
<xs:element ref="orgPOBox"/>
<xs:element ref="orgCity"/>
<xs:element ref="orgPostalcode"/>
<xs:element ref="orgProvince"/>
<xs:element ref="orgCountry"/>
<xs:element ref="orgPhone"/>
<xs:element ref="orgFax"/>
<xs:element ref="orgWebsite"/>
<xs:element ref="orgEmail"/>
</xs:sequence>
</xs:complexType>
<!-- ELEMENT
DECLARATIONS -->
<xs:element name="orgTitle" type="xs:string"/>
<xs:element name="orgAcronym" type="xs:string"/>
<xs:element name="orgDesc" type="xs:string"/>
<xs:element name="orgParentInstitution" type="xs:string"/>
<xs:element name="orgAddress" type="xs:string"/>
<xs:element name="orgPOBox" type="xs:string"/>
<xs:element name="orgCity" type="xs:string"/>
<xs:element name="orgPostalcode" type="xs:string"/>
<xs:element name="orgProvince" type="xs:string"/>
<xs:element name="orgCountry" type="xs:string"/>
<xs:element name="orgPhone" type="xs:string"/>
<xs:element name="orgFax" type="xs:string"/>
<xs:element name="orgWebsite" type="xs:string"/>
<xs:element name="orgEmail" type="xs:string"/>
<xs:element name="orgContactName" type="xs:string"/>
<xs:element name="orgContactPhone" type="xs:string"/>
<xs:element name="orgContactEmail" type="xs:string"/>
<xs:element name="orgContactRole" type="xs:string"/>
<xs:element name="orgSuppInfo" type="xs:string"/>
<xs:element name="mdFileID" type="xs:string"/>
</xs:schema>
4- Geonetwork specific stylesheet files : /web/xml/schemas/organisation/…
Geonetwork’s api will need few xsl files in your schema’s folder in order to perform various operations such as getting the uuid or the thumbnail. Here is a very simple version of the each files needed. You can just copy paste them. Perhaps, more complexes operations can be done. I suggest looking at the fgdc-std or iso19115 files for complete examples.
extract-thumbnails.xsl
<?xml
version="1.0"
encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="metadata">
<thumbnail/>
</xsl:template>
</xsl:stylesheet>
extract-uuid.xsl
<?xml
version="1.0"
encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="metadata">
<uuid><xsl:value-of select="mdFileID"/></uuid>
</xsl:template>
</xsl:stylesheet>
schema-suggestions.xml
this file seam to be there for informative purposes, leave-it blank
<?xml
version="1.0"
encoding="UTF-8"?>
<fields>
<!--
<field name="">
<suggest
name=""/>
</field>
-->
</fields>
set-thumbnail.xsl
<?xml
version="1.0"
encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<xsl:apply-templates select="metadata"/>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
unset_thumbnail.xsl
<?xml
version="1.0"
encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<xsl:apply-templates select="metadata"/>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
update-fixed-info.xsl
<?xml
version="1.0"
encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<xsl:apply-templates select="metadata"/>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
5- Geonetwork’s searching stylesheet : /web/xml/search/organisation.xsl
By default, Geonetwork’s search engine will search the “title”, “abstract”, “keywords” and “geographic box”. So you need to match at least one of those with your metadata schema. In our organisation example, there is no coverage region or keywords, but you can look at the other templates.
<?xml
version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<Document>
<xsl:apply-templates select="/metadata/orgTitle">
<xsl:with-param name="name"
select="'title'"/>
<xsl:with-param name="token" select="'true'"/>
</xsl:apply-templates>
<xsl:apply-templates select="/metadata/orgDesc">
<xsl:with-param name="name"
select="'abstract'"/>
<xsl:with-param name="token" select="'true'"/>
</xsl:apply-templates>
<Field name="any" store="false" index="true" token="true">
<xsl:attribute name="string">
<xsl:apply-templates select="/metadata" mode="allText"/>
</xsl:attribute>
</Field>
<!--
locally
searchable fields -->
<!--
defaults
to true -->
<Field name="digital" string="true" store="false" index="true" token="false"/>
</Document>
</xsl:template>
<!-- text element, by
default indexed, not stored nor tokenized
-->
<xsl:template match="*">
<xsl:param name="name"
select="name(.)"/>
<xsl:param name="store" select="'false'"/>
<xsl:param name="index" select="'true'"/>
<xsl:param name="token" select="'false'"/>
<Field name="{$name}" string="{string(.)}" store="{$store}" index="{$index}" token="{$token}"/>
</xsl:template>
<!-- codelist element,
indexed, not stored nor tokenized -->
<xsl:template match="*[./*/@value]">
<xsl:param name="name" select="name(.)"/>
<Field name="{$name}" string="{*/@value}" store="false" index="true" token="false"/>
</xsl:template>
<!--allText -->
<xsl:template match="*" mode="allText">
<xsl:for-each select="@*"><xsl:value-of select="concat(string(.),' ')"/></xsl:for-each>
<xsl:choose>
<xsl:when test="*"><xsl:apply-templates select="*" mode="allText"/></xsl:when>
<xsl:otherwise><xsl:value-of select="concat(string(.),'
')"/></xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
6- Your own Schema’s Stylesheet : /web/xsl/metadata-organisation.xsl
This is the file you can end up playing with for days without knowing what you’re doing… and… on top of that… expecting to have some results. I wish no body will ever go through those days after me, this is why I’m writing this document.
This is the stylesheet that will be used by geonetwork to show the content of your metadata according to user’s request for viewing or editing it. In both case, it is possible for the user to choose between the “simple”, “advanced” or “xml” view. Depending on what the user is doing with the metadata, we need to show it different ways. Note that there is no need for any specification in the “xml” view, since we simply show the raw metadata in it’s xml form.
<?xml
version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:geonet="http://www.fao.org/geonetwork">
<!--
default: in simple mode just
a flat list
-->
<xsl:template mode="organisation" match="*|@*">
<xsl:param name="schema"/>
<xsl:param name="edit"/>
<xsl:apply-templates mode="element" select=".">
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="edit"
select="$edit"/>
<xsl:with-param name="flat"
select="$currTab='simple'"/>
</xsl:apply-templates>
</xsl:template>
<!--
these elements should be
boxed
-->
<xsl:template mode="organisation" match="orgContactInfo|orgContactus">
<xsl:param name="schema"/>
<xsl:param name="edit"/>
<xsl:apply-templates mode="complexElement" select=".">
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="edit"
select="$edit"/>
</xsl:apply-templates>
</xsl:template>
<!--
make the following fields
always not editable:
mdFileID
-->
<xsl:template mode="organisation" match="mdFileID">
<xsl:param name="schema"/>
<xsl:param name="edit"/>
<xsl:apply-templates mode="element" select=".">
<xsl:with-param name="schema"
select="$schema"/>
<xsl:with-param name="edit"
select="false()"/>
</xsl:apply-templates>
</xsl:template>
<!--
orgDesc, orgSuppInfo
-->
<xsl:template mode="organisation" match="orgDesc|orgSuppInfo">
<xsl:param name="schema"/>
<xsl:param name="edit"/>
<xsl:apply-templates mode="simpleElement" select=".">
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="edit"
select="$edit"/>
<xsl:with-param name="text">
<xsl:call-template name="getElementText">
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="edit"
select="$edit"/>
<xsl:with-param name="rows"
select="5"/>
</xsl:call-template>
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<!-- -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<!--
organisation brief formatting -->
<!--
this
formating is used to show search results -->
<!-- -
- - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<xsl:template name="organisationBrief">
<metadata>
<title><xsl:value-of select="orgTitle"/></title>
<abstract><xsl:value-of select="orgDesc"/></abstract>
<xsl:copy-of select="geonet:info"/>
</metadata>
</xsl:template>
</xsl:stylesheet>
7- Modifying of geonetwork’s config files.
/web/WEB-INF/config.xml
Add this line into the <gui> section :
<xml name="organisation" file="xml/organisation.xml" />
/web/xsl/metadata-edit.xsl
if you want your metadata schema to have a thumbnail, add a line like this into the “edit button” template section (<xsl:template name="editButtons" …>):
<!--
thumbnails
-->
<xsl:if test="string(geonet:info/schema)='organisation'">
 
<button class="content" onclick="doAction('{/root/gui/locService}/metadata.thumbnail.form')">
<xsl:value-of select="/root/gui/strings/thumbnails"/>
</button>
</xsl:if>
/web/xsl/metadata-utils.xsl
Add this line at the top :
<xsl:include href="metadata-organisation.xsl"/>
and this line into the <!-- brief --> section:
<!-- organisation -->
<xsl:when test="$schema='organisation'">
<xsl:call-template name="organisationBrief"/>
</xsl:when>
/web/xsl/metadata.xsl
Add these lines into the <!-- main schema switch -->
<!-- organisation -->
<xsl:when test="$schema='organisation'">
<xsl:apply-templates mode="organisation" select="." >
<xsl:with-param name="schema" select="$schema"/>
<xsl:with-param name="edit"
select="$edit"/>
</xsl:apply-templates>
</xsl:when>
8 – Database integration (I’m using SQLYog)
A) metadata table
Add organisation_template.xml to your table.
Make sure the id is unique
schemaid must be your schema’s name “organisation”
isTemplate must be set to “y”
data must be an exact copy of organisation_template.xml (see section “1 – General structure“). If you worry about the tabs and carriage returns, just delete them.
uuid, you can have your own generated by the International Telecommunication Union at :
http://www.itu.int/ITU-T/asn1/cgi-bin/uuid_generate
SQL statement example:
insert into `metadata`
(`id`,`schemaId`,`isTemplate`,`createDate`,`lastChangeDate`,`data`,`source`,`sourceUri`,`uuid`)
values ( '30', 'organisation' ,'y', '2007-06-21T15:21:47', '2007-06-21T15:21:47' ,'<metadata><orgTitle>New organisation</orgTitle><orgAcronym/><orgParentInstitution/><orgDesc/><orgSuppInfo/><orgContactus><orgAddress/><orgPOBox/><orgCity/><orgPostalcode/><orgProvince/><orgCountry/><orgPhone/><orgFax/><orgWebsite/><orgEmail/></orgContactus> <orgContactInfo><orgContactName/><orgContactRole/><orgContactEmail/><orgContactPhone/> </orgContactInfo> <mdFileID>d5750700-1da8-11dc-95c5-0002a5d5c51b</mdFileID></metadata>','myGeoNet',NULL,'d5750700-1da8-11dc-95c5-0002a5d5c51b')
B) operationallowed table
The default groupId to give access to is “2”
The metadataId is 30 (see above)
The operationId is by default 0,1,2,4,5,6
(Do I need to specify to make one entry per operationId?)
9 – Testing
Connect to your geonetwork, choose your new schema, and create a new metadata!