Installation
The intention of the feeds view is that users can subscribe given XML feeds, read them and import relevant XML feed items as Sophora documents for further usage.
The administrator has to declare the available XML feeds in the Administration section and define the XSL transformation of the XML feed items into Sophora XML. The created Sophora XML will be imported into the Sophora system when the user imports the feed item via clicking the import icon in the top left corner of the feed item.
The very first time the feeds view is opened in the Sophora DeskClient (User >> Views >> Feeds) a dialog appears and asks for permission to register the required node types. After registration, (re-)open the Administration view which then contains two new entries: XML Feeds and XSL.
If you declined the registration in the dialog, it can be triggered again by restarting the DeskClient and opening the Feeds view again.
Configuring XML Feeds
To configure feeds, at least two documents are required:
- a XML feed configuration document and
- a corresponding transformation document.
An XML Feed
To create a new XML feed, open the context menu of the XML Feeds entry and select New: XML Feed.
Each feed requires a name, the feed URL, a brief description (like the provider name), some XPath queries to read the XML items from the XML feed and a reference to an XSL transformation which transforms the feed items into valid Sophora XML, e.g. story documents.
The most important XPath field is the field Item-XPath. This XPath expression is applied to the complete XML document of the feed. It defines how the Feeds view finds the items in the XML feed. All other XPath expressions are relative to the XML snippet of the particular feed item. Only the XPath expression Item-XPath differs in this context: This XPath expression is applied to the result XML of the transformation process.
The name field is used to display the feed within the feeds view, grouped by the provider. The feed description appears as tooltip on each feed. The XPath fields, like Title XPath, Description XPath or Date XPath, declare the paths to the particular fields within the feed item, so that these fields can be displayed in the UI of the feeds view.
Some feed items contain an URL which points to an XML document with further and detailed content. If so, the Detail XPath field needs to be filled in, in order to find such URL within the feed item and get the actual content from the retrieved XML document.
The fields ID Stem and Structure Node contain the default Sophora ID stem and location for the imported documents. These fields are given as parameters idStem and structureNodePath to the XSL transformation process of the feed item. Moreover, custom parameters may be added to the XSL transformation by inserting them into the XSL Parameters table. So the same XSL transformation can be used for several feeds, but with different parameter values.
To check whether a feed item is already imported as a Sophora document or to update an already imported document, the external ID of the document is needed. The path to the external ID in the transformed feed item (that means the resulting Sophora XML) is defined in the field ExternalID XPath.
If the display of the item in the feeds view should contain a teaser image, the field Teaser Image XPath is required as well to get the URL of that image.
The Transformation
To create a new XSL transformation, open the context menu of the XSL entry and select New: XSL.
Each XSL transformation consists of a name and the XSL code that transforms a feed item XML into Sophora XML.
There are a few predefined XSL template parameters which are set during the transformation process and thus can be used in the XSL templates.
Variable | Description |
---|---|
feedUrl | This is the URL of the feed. |
detailUrl | If the feed uses detail XML documents, this parameter is set to the URL of the detail document for the current item. |
idStem | This is the ID stem set in the feed configuration document. |
structureNodePath | The structureNodePath contains the complete path as set in the feed configuration document; from the site 'down' to the target structure node. |
To access these variables you only have to declare the parameters in the head of the XSL template as is shown in the following example code.
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="1.0">
<!-- Declaring the predefined parameters . -->
<xsl:param name="idStem" />
<xsl:param name="structureNodePath" />
[...]
<xsl:template match="story">
<!-- Using a predefined parameter. -->
<idstem>
<xsl:value-of select="$idStem" />
</idstem>
</xsl:template>
</xsl:stylesheet>
Accessing custom parameters of a feed is analogous (defined within XSL Parameters
table of its configuration document as explained above): If a parameter, for instance myCustomParameter
, has been added to the XSL Parameters
table of a feed, it is given to the XSL transformation process. There its value can be accessed via the variable $myCustomParameter
if it was declared via an XSL-"param"-element: <xsl:param name="myCustomParameter" />
.
Exemplary Transformation
The following XSL template transforms an RSS/Metaplus feed item into the Sophora XML of a document of type "sophora-content-nt:story
" with an external ID depending on the feed item. This XSL also transforms the teaser image information (if present) and thus an image document will be created along with the story document.
<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0" xmlns:sophora="http://www.sophoracms.com/import/2.3"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rss="http://purl.org/rss/1.0/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<xsl:output indent="yes" />
<!-- Define the special parameters for ID stem and structure node -->
<xsl:param name="idStem" />
<xsl:param name="structureNodePath" />
<xsl:template match="/rss:item">
<sophora:documents>
<!-- Determine the external ID of the Sophora document -->
<xsl:variable name="externalID">
<xsl:text>ts_rss_import_</xsl:text>
<xsl:choose>
<xsl:when test="dc:identifier and normalize-space(dc:identifier) != ''">
<xsl:value-of select="dc:identifier" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="@rdf:about" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<!-- Determine the external ID of the teaser image of the Sophora document -->
<xsl:variable name="externalIDImage"><xsl:value-of select="$externalID" />_image</xsl:variable>
<!-- Create the Sophora document (a story) -->
<sophora:document nodeType="sophora-content-nt:story" externalID="{$externalID}">
<!-- Fill the documents properties with data of the feed item -->
<sophora:properties>
<sophora:property name="sophora-content:topline">
<sophora:value>
<xsl:value-of select="substring-after(dc:subject, '/')" />
</sophora:value>
</sophora:property>
<sophora:property name="sophora-content:title">
<sophora:value>
<xsl:value-of select="rss:title" />
</sophora:value>
</sophora:property>
<sophora:property name="sophora-content:shorttext">
<sophora:value>
<xsl:value-of select="rss:description" />
</sophora:value>
</sophora:property>
</sophora:properties>
<!-- Add a reference to the Sophora document of the teaser image -->
<sophora:childNodes>
<xsl:if test="*[local-name() = 'image' and contains(namespace-uri(), 'metaplus')]">
<sophora:childNode nodeType="sophora-content-nt:imageref" name="sophora-content:image">
<sophora:properties>
<sophora:property name="sophora:reference">
<sophora:value>
<xsl:value-of select="$externalIDImage" />
</sophora:value>
</sophora:property>
</sophora:properties>
<sophora:childNodes />
<sophora:resourceList>
<xsl:apply-templates
select="*[local-name() = 'image' and contains(namespace-uri(), 'metaplus')]">
<xsl:sort
select="*[local-name() = 'width' and contains(namespace-uri(), 'metaplus')]"
order="descending" />
<xsl:with-param name="externalIDImage" select="$externalIDImage" />
</xsl:apply-templates>
</sophora:resourceList>
</sophora:childNode>
</xsl:if>
</sophora:childNodes>
<sophora:resourceList />
<!-- Set the special fields of the Sophora document -->
<sophora:fields>
<!-- Set the site -->
<sophora:site>
<xsl:call-template name="getSiteFromStructureNodePath" />
</sophora:site>
<!-- Set the structure node -->
<sophora:structureNode>
<xsl:call-template name="getStructureNodeFromStructureNodePath" />
</sophora:structureNode>
<sophora:categories />
<!-- Set the ID stem -->
<sophora:idstem>
<xsl:if test="$idStem != ''">
<xsl:value-of select="$idStem" />
</xsl:if>
</sophora:idstem>
<sophora:forceLock>false</sophora:forceLock>
<sophora:forceCreate>false</sophora:forceCreate>
<sophora:enabledChannels />
<sophora:disabledChannels />
</sophora:fields>
<sophora:instructions>
<sophora:lifecycleActivities />
<sophora:proposals />
</sophora:instructions>
</sophora:document>
</sophora:documents>
</xsl:template>
<xsl:template match="*[local-name() = 'image' and contains(namespace-uri(), 'metaplus')]">
<xsl:param name="externalIDImage" />
<xsl:if test="position() = 1">
<!-- Create the Sophora document of the teaser image -->
<sophora:document nodeType="sophora-extension-nt:image" externalID="{$externalIDImage}">
<!-- Fill the documents properties with data of the feed item -->
<sophora:properties>
<sophora:property name="sophora-extension:alttext">
<sophora:value>
<xsl:value-of select="*[local-name() = 'alt' and contains(namespace-uri(), 'metaplus')]" />
</sophora:value>
</sophora:property>
<sophora:property name="sophora-extension:caption">
<sophora:value>
<xsl:value-of select="*[local-name() = 'caption' and contains(namespace-uri(), 'metaplus')]" />
</sophora:value>
</sophora:property>
</sophora:properties>
<!-- Add the original image data -->
<sophora:childNodes>
<sophora:childNode nodeType="sophora-extension-nt:imagedata" name="sophora-extension:imagedata">
<sophora:properties>
<sophora:property name="sophora-extension:binarydata" mimetype="image/jpeg">
<sophora:value>
<xsl:value-of select="*[local-name() = 'data' and contains(namespace-uri(), 'metaplus')]" />
</sophora:value>
</sophora:property>
<sophora:property name="sophora-extension:imagetype">
<sophora:value>original</sophora:value>
</sophora:property>
</sophora:properties>
<sophora:childNodes />
<sophora:resourceList />
</sophora:childNode>
</sophora:childNodes>
<sophora:resourceList />
<!-- Set the special fields of the Sophora document -->
<sophora:fields>
<!-- Set the site -->
<sophora:site>
<xsl:call-template name="getSiteFromStructureNodePath" />
</sophora:site>
<!-- Set the structure node -->
<sophora:structureNode>
<xsl:call-template name="getStructureNodeFromStructureNodePath" />
</sophora:structureNode>
<sophora:categories />
<!-- Set the ID stem -->
<sophora:idstem>image</sophora:idstem>
<sophora:forceLock>false</sophora:forceLock>
<sophora:forceCreate>false</sophora:forceCreate>
<sophora:enabledChannels />
<sophora:disabledChannels />
</sophora:fields>
<sophora:instructions>
<sophora:lifecycleActivities />
<sophora:proposals />
</sophora:instructions>
</sophora:document>
</xsl:if>
</xsl:template>
<!-- Returns the site from 'structureNodePath' -->
<xsl:template name="getSiteFromStructureNodePath">
<xsl:variable name="pathTemp" select="substring-after($structureNodePath, '/')" />
<xsl:choose>
<xsl:when test="contains($pathTemp, '/')">
<xsl:value-of select="substring-before($pathTemp, '/')" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pathTemp" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Returns the structure node path without the site name from 'structureNodePath' -->
<xsl:template name="getStructureNodeFromStructureNodePath">
<xsl:variable name="pathTemp" select="substring-after($structureNodePath, '/')" />
<xsl:choose>
<xsl:when test="contains($pathTemp, '/')">
<xsl:text>/</xsl:text>
<xsl:value-of select="substring-after($pathTemp, '/')" />
</xsl:when>
<xsl:otherwise>
<xsl:text>/</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet> <xsl:text>/</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
Caching
The downloaded feeds and transformed feed items are cached within the Feeds View. To configure the duration of caching the following parameter can be set in the configuration document.
Parameter | Description | Example |
---|---|---|
feeds.cache.expirationTime | Expiration time of cached XML feeds in minutes. Set to 0 to disable caching. Default is 60 (1 hour). | 120 |