XIP aus RSS-Feed

Aus SiteparkWiki
Zur Navigation springen Zur Suche springen

Mit folgendem Beispiel lässt sich ein RSS-Feed (Version 2.0) importieren. Die einzelnen Einträge werden als Resource-Artikel angelegt. Der Anchor der Resource-Artikel ergibt sich aus der Position innerhalb des RSS-Feed.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <xip>
            <xsl:for-each select="/rss/channel/item">
                <resource parent="rss.channel.x" name="{title}" anchor="rss.channel.x.item.{position()}">
                    <text name="description"><xsl:value-of select="description"/></text>
                    <url name="link"><xsl:value-of select="link"/></url>
                    <binary name="enclosure" url="{enclosure/@url}"/>
                </resource>
            </xsl:for-each>
        </xip>
    </xsl:template>

</xsl:stylesheet>

Beim obigen Beispiel hat die Verwendung der Position des Items innerhalb des RSS-Feed als Anchor zur Folge, das ein bestimmter Resource-Artikel bei Änderung des RSS-Feeds immer andere Daten enthält. Dies ist nicht immer gewünscht. Um dieses Problem zu lösen muss ein Eindeutige Anchor vergeben werden. Im RSS-Feed gibt es das Element <guid>, mit dem der Eintrag eindeutig identifiziert werden kann. Oftmals ist dieser Wert eine URL. Der Wert kann nicht direkt als Anchor verwendet werden, da in einer URL Zeichen enthalten sind, die in einem Anchor nicht enthalten sein dürfen.

Im folgenden Beispiel wird dieses Problem gelöst, indem ein Hash-Wert des <guid>-Elementes erzeugt wird.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:xip="http://ies.sitepark.com/xip"
            extension-element-prefixes="xip">

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <!--
     xs:decimal xip:hashCode(String s)
     Erzeugt aus einer Zeichenkette einen Hash-Code
    -->
    <xsl:function name="xip:hashCode">
        <xsl:param name="s"/>
        <xsl:value-of select="xs:decimal(xs:double(xip:hashCode($s, 1, 0)))"/>
    </xsl:function>
    <xsl:function name="xip:hashCode">
        <xsl:param name="s"/>
        <xsl:param name="i"/>
        <xsl:param name="h"/>
        <xsl:variable name="code" select="string-to-codepoints(substring($s, $i, 1))"/>
        <xsl:variable name="len" select="string-length($s)"/>
        <xsl:choose>
            <xsl:when test="($i + 1) &lt;= $len">
                <xsl:value-of select="xip:hashCode($s, $i+1, $h*31 + $code)"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$h*31 + $code"/>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:function>


    <xsl:template match="/">
        <xip>
            <xsl:for-each select="/rss/channel/item">
                <resource parent="rss.channel.spiegel" name="{title}" code="{string-to-codepoints(guid)}" anchor="rss.channel.spiegel.item.{xip:hashCode(guid)}">
                    <text name="description"><xsl:value-of select="description"/></text>
                    <url name="link"><xsl:value-of select="link"/></url>
                    <binary name="enclosure" url="{enclosure/@url}"/>
                </resource>
            </xsl:for-each>
        </xip>
    </xsl:template>

</xsl:stylesheet>

Weiterhin wäre es denkbar, wenn das Datum in einer geeigneteren Form ausgegeben würde. Hierzu könnte ein Template mit folgender Funktion verwendet werden:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

    <xsl:template match="/">
        <xip>
            <xsl:for-each select="/rss/channel/item">
                <resource parent="rss.pool" name="{title}" anchor="rss.item.{position()}">
                    <text name="sp_date">
                        <xsl:variable name="d" select="pubDate"/>
                        <xsl:call-template name="formatDate">
                            <xsl:with-param name="date" select="$d" />
                        </xsl:call-template>
                    </text>
                    <text name="sp_intro"><xsl:value-of select="description"/></text>
                    <url name="sp_link"><xsl:value-of select="link"/></url>
                    <binary name="sp_bild" url="{enclosure/@url}"/>
                </resource>
            </xsl:for-each>
        </xip>
    </xsl:template>

    <xsl:template name="formatDate">
      <xsl:param name="date" /><!-- Tue, 09 Mar 2010 11:21:18 +0100 -->

      <xsl:variable name="dayString" select="substring-before($date, ',')" />
      <xsl:variable name="tmp" select="substring-after($date, ' ')" /><!-- 09 Mar 2010 11:21:18 +0100 -->

      <xsl:variable name="day" select="substring-before($tmp, ' ')" />
      <xsl:variable name="tmp" select="substring-after($tmp, ' ')" /><!-- Mar 2010 11:21:18 +0100 -->

      <xsl:variable name="monthString" select="substring-before($tmp, ' ')" />
      <xsl:variable name="month" select="substring(
        substring-after(
            'Jan=01;Feb=02;Mar=03;Apr=04;May=05;Jun=06;Jul=07;Aug=08;Sep=09;Oct=10;Nov=11;Dec=12',
            $monthString),
        2,
        2)" /><!-- englich month strings -->
      <xsl:variable name="tmp" select="substring-after($tmp, ' ')" /><!-- 2010 11:21:18 +0100 -->

      <xsl:variable name="year" select="substring-before($tmp, ' ')" />
      <xsl:variable name="tmp" select="substring-after($tmp, ' ')" /><!-- 11:21:18 +0100 -->

      <xsl:variable name="hour" select="substring-before($tmp, ':')" />
      <xsl:variable name="tmp" select="substring-after($tmp, ':')" /><!-- 21:18 +0100 -->

      <xsl:variable name="minute" select="substring-before($tmp, ':')" />
      <xsl:variable name="tmp" select="substring-after($tmp, ':')" /><!-- 18 +0100 -->

      <xsl:variable name="second" select="substring-before($tmp, ' ')" />
      <xsl:variable name="tmp" select="substring-after($tmp, ' ')" /><!-- +0100 -->

      <xsl:variable name="timezone" select="$tmp" />

      <xsl:value-of select="concat($day, '.', $month, '.', $year, ' ', $hour, ':', $minute, ':', $second)" />
    </xsl:template>

</xsl:stylesheet>

XIP mit XSLT