Mit XML + XSL Glossarbegriffe Erkennen und Verlinken
Walter
- xsl
0 Mandatsträger a.D.0 Walter
0 Thomas J.S.0 Walter0 Walter0 Thomas J.S.
Hallo Commumity,
ich habe eine XML Datei mit viel Text und ein Glossar. Zu jedem Glossarbegriff habe ich ein Schlagwort/Suchwort
Wollte nun Fragen ob es mit Hilfe von XSLT irgendwie möglich ist das ich den Inhalt von den Elementen nach den Schlagworten durchsuche und sobald er eines im Text findet, einen Link zu dem Text vom Glossar einfügt.
Von dem Aufbau der XML Datei soll sich ansonsten nichts ändern
Grober Aufbau der XML Datei:
<root>
<kapitel>
<seite>
<zeile ein="true"> Hier steht ganz viel Inhalt. Sobald ein Begriff hier auftaucht der im Glossar näher erklärt ist, soll dieser zu einem Link werden der an die richtige Stelle im Glossar verweist</zeile>
<marku>Auch andere Elemente kommen im Seiten Element vor</marku>
</seite>
<seite>....</seite><seite>....</seite><seite>....</seite>
</kapitel>
</root>
Grüße, Walter
Hi,
Wollte nun Fragen ob es mit Hilfe von XSLT irgendwie möglich ist das ich den Inhalt von den Elementen nach den Schlagworten durchsuche und sobald er eines im Text findet, einen Link zu dem Text vom Glossar einfügt.
ja geht.
Und um den SELF-Gedanken etwas zu pflegen: Was hast Du probiert und hat nicht gefunzt?
Mandatsträger a.D.
Hi Mandatsträger,
ich hatte es so probiert und dabei viele Varianten von Schleifen etc. ausprobiert was aber nie geklappt hatte:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/ | @* | node()">
xsl:copy
<xsl:for-each select="text()">
<xsl:if test="contains(text(),//glossar@titel)">
<xsl:element name="glossarref">
<xsl:attribute name="titel"><xsl:value-of select="@titel" /></xsl:attribute>
<xsl:attribute name="inhalt"><xsl:value-of select="." /></xsl:attribute>
</xsl:element>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="node() | @* " />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Hallo,
ich habe eine XML Datei mit viel Text und ein Glossar. Zu jedem Glossarbegriff habe ich ein Schlagwort/Suchwort
Wollte nun Fragen ob es mit Hilfe von XSLT irgendwie möglich ist das ich den Inhalt von den Elementen nach den Schlagworten durchsuche und sobald er eines im Text findet, einen Link zu dem Text vom Glossar einfügt.
Von dem Aufbau der XML Datei soll sich ansonsten nichts ändernGrober Aufbau der XML Datei:
<root>
<kapitel>
<seite>
<zeile ein="true"> Hier steht ganz viel Inhalt. Sobald ein Begriff hier auftaucht der im Glossar näher erklärt ist, soll dieser zu einem Link werden der an die richtige Stelle im Glossar verweist</zeile>
<marku>Auch andere Elemente kommen im Seiten Element vor</marku>
</seite>
<seite>....</seite><seite>....</seite><seite>....</seite>
</kapitel>
</root>
Das könnte so gehen:
<xsl:template match="seite//text()">
<xsl:call-template name="makelink">
<xsl:with-param name="text" select="normalize-space(.)" />
</xsl:call-template>
</xsl:template>
<xsl:template name="makelink">
<xsl:param name="text" />
<xsl:variable name="wort" select="substring-before($text, ' ')" />
<xsl:if test="$wort != ''">
xsl:choose
<xsl:when test="$wort = /root/glossar/eintrag/titel">
<a href="#{generate-id(/root/glossar/eintrag[titel = $wort])}"><xsl:value-of select="$wort" /></a>xsl:text </xsl:text>
</xsl:when>
xsl:otherwise
<xsl:value-of select="concat($wort, ' ')" />
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="makelink">
<xsl:with-param name="text" select="normalize-space(substring-after($text, $wort))" />
</xsl:call-template>
</xsl:if>
</xsl:template>
Damit du sieht was da passiert hier ein koplettest Bsp:
--------- xml ---------------
<?xml version="1.0" encoding="iso-8859-1"?>
<root>
<kapitel>
<seite>
<zeile ein="true">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nullam tincidunt. Nulla sit amet urna in est gravida interdum. Aenean suscipit. Vestibulum
non augue.<foo>Vivamus luctus enim ac nunc adipiscing dictum. Nunc ac lorem eget dolor aliquam laoreet. Suspendisse potenti.</foo> Fusce urna. Nunc
congue, neque eu pharetra commodo, turpis dolor molestie erat, a adipiscing ipsum lacus a nisl. Quisque eget elit. Morbi odio. Duis sit amet pede.
Vivamus sed enim in erat vehicula fringilla. Duis viverra. Nam condimentum, mi vel mollis vulputate, libero orci sodales urna, a tempor odio lectus
eget wisi. <bar>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Aliquam vestibulum tortor nec turpis.</bar>
Aenean suscipit adipiscing sem. Vivamus id felis. Praesent ornare malesuada tortor.
</zeile>
</seite>
<seite>
Cras ultricies. Vivamus elementum, sapien quis rhoncus feugiat, nibh est posuere purus, a fringilla ante nibh at turpis. Fusce ante tortor, consequat
eu, sollicitudin quis, <foo>bibendum at, sem. Cras venenatis mollis risus. <bar>Quisque condimentum gravida arcu. Donec rutrum mauris in sapien.</bar>
Pellentesque aliquam suscipit felis. Cras velit. Cras malesuada ligula et tellus. Ut lacus. Donec feugiat. Vivamus justo. Curabitur feugiat.</foo> Nullam
lorem odio, venenatis non, ultrices a, facilisis sit amet, metus. Maecenas elit.
</seite>
</kapitel>
<glossar>
<eintrag>
<titel>Vivamus</titel>
<text>bla bla bla bla</text>
</eintrag>
<eintrag>
<titel>Vestibulum</titel>
<text>bla bla bla</text>
</eintrag>
<eintrag>
<titel>condimentum</titel>
<text>bla bla bla</text>
</eintrag>
</glossar>
</root>
------------------- xsl ---------------------
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title>Untitled</title>
</head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="kapitel/seite">
<p>
<xsl:apply-templates />
</p>
</xsl:template>
<xsl:template match="seite//*">
<span style="color:red">[<xsl:value-of select="name()" />]</span>
<xsl:apply-templates />
<span style="color:red">[/<xsl:value-of select="name()" />]</span>
</xsl:template>
<xsl:template match="seite//text()">
<strong>{</strong><xsl:call-template name="makelink">
<xsl:with-param name="text" select="normalize-space(.)" />
</xsl:call-template><strong>}</strong>
</xsl:template>
<xsl:template match="glossar">
<dl>
<xsl:for-each select="eintrag">
<dd id="{generate-id(.)}">
<xsl:value-of select="titel" />
</dd>
<dt>
<xsl:value-of select="text" />
</dt>
</xsl:for-each>
</dl>
</xsl:template>
<xsl:template name="makelink">
<xsl:param name="text" />
<xsl:variable name="wort" select="substring-before($text, ' ')" />
<xsl:if test="$wort != ''">
xsl:choose
<xsl:when test="$wort = /root/glossar/eintrag/titel">
<a href="#{generate-id(/root/glossar/eintrag[titel = $wort])}"><xsl:value-of select="$wort" /></a>xsl:text </xsl:text>
</xsl:when>
xsl:otherwise
<xsl:value-of select="concat($wort, ' ')" />
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="makelink">
<xsl:with-param name="text" select="normalize-space(substring-after($text, $wort))" />
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Grüße
Thomas
@Thomas,
vielen Dank so funktioniert es, lediglich ein Problem ist dass das letzte Wort vor dem Schlusstag nicht mit übernommen wird wegen substring-before ' ' und keine Leerzeichen vor dem Schlusselement ist.
Wollte nun mit substring-after das Wort selektieren aber mir fehlt eine Funktion wie ich das letzte ' ' Leerzeichen finde im jeweiligen Element. Wäre super wenn dafür jemand eine Lösung hätte.
Grüße,
Walter
<xsl:template match="seite//text()">
<xsl:call-template name="makelink">
<xsl:with-param name="text" select="normalize-space(.)" />
</xsl:call-template>
</xsl:template><xsl:template name="makelink">
<xsl:param name="text" />
<xsl:variable name="wort" select="substring-before($text, ' ')" />
<xsl:if test="$wort != ''">
xsl:choose
<xsl:when test="$wort = /root/glossar/eintrag/titel">
<a href="#{generate-id(/root/glossar/eintrag[titel = $wort])}"><xsl:value-of select="$wort" /></a>xsl:text </xsl:text>
</xsl:when>
xsl:otherwise
<xsl:value-of select="concat($wort, ' ')" />
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="makelink">
<xsl:with-param name="text" select="normalize-space(substring-after($text, $wort))" />
</xsl:call-template>
</xsl:if>
</xsl:template>
Hat sich erledigt. Habe das erste Template folgendermaßen geändert:
<xsl:template match="seite//text()">
<xsl:call-template name="makelink">
<xsl:with-param name="text" select="concat(normalize-space(.), ' test')" />
</xsl:call-template>
</xsl:template>
Vielen Dank nochmal
Hallo,
vielen Dank so funktioniert es, lediglich ein Problem ist dass das letzte Wort vor dem Schlusstag nicht mit übernommen wird wegen substring-before ' ' und keine Leerzeichen vor dem Schlusselement ist.
Änder die Zeile in Template so ab, dann brauchst du nicht auf Test-Wörter zuruckzugreifen.
<xsl:template name="makelink">
...
<xsl:call-template name="makelink">
<xsl:with-param name="text" select="concat(normalize-space(substring-after($text, $wort)), ' ')" />
Grüße
Thomas