Reputation: 488
I have a set of XML files where place names (in divergent historic spelling) are tagged as
<place>
: cf. sample file. The place tag also contains the attribute link
, whose value is a hyperlink to a World Historical Gazetteer page, e.g.:
<place name="Wien" type="place_of_issue"
link="http://whgazetteer.org/places/12346175/portal">Wien</place>
Converting the XML files to HTML with XSLT, I want every such tag in the text to be replaced by a hyperlink <a href>
, linking to the same WHG URL.
A minimal version of my XSL based on Michael Hor-257k's answer is:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"/>
<xsl:template match="/">
<!-- Jekyll statement -->
---
<xsl:for-each select="source/metadata/digital_surrogate">
layout: page
title: <xsl:value-of select="@filename"/>
permalink: /<xsl:value-of select="@filename"/>/
exclude: true
---
</xsl:for-each>
<!-- Get transcription with links -->
<div class="flex-container">
<div><p><strong>Transkription:</strong></p>
<p><xsl:apply-templates select="//div">
</xsl:apply-templates>
<!-- include WHG links -->
<xsl:for-each select="//place">
<p>Genannte Orte im World Historical Gazetteer:</p>
<a href="{//place/@link}" target="_blank">
<xsl:value-of select="."/>
</a><br/>
</xsl:for-each>
</p><br/>
</div>
</div>
</xsl:template>
</xsl:stylesheet>
This at least correctly displays all place names mentioned in the correct order, with correct WHG links and correct names:
<a href="http://whgazetteer.org/places/12346175/portal" target="_blank">Wien</a>
<a href="http://whgazetteer.org/places/13067462/portal" target="_blank">Maintz</a>
<a href="http://whgazetteer.org/places/12346175/portal" target="_blank">Wien</a>
However, the links still appear below the transcription, not within.
My desired HTML output would be:
<div class="flex-container">
<div>
<p><strong>Transkription:</strong></p>
<p>
Wir Vorsteher und gesamte
Meister des ehrsamen Handwerks der bürgerl:[ichen] Tischlern in der K:[aiserlich]
K:[öniglichen] Haubt = und Residenz Stadt <a href="http://whgazetteer.org/places/12346175/portal" target="_blank">Wien</a> (beglaubigen) hiermit,
daß gegenwertiger Tischlergesell, Namens Georg
Gramer von <a href="http://whgazetteer.org/places/13067462/portal" target="_blank">Maintz</a> - -
[etc.]
</p>
</div>
</div>
Upvotes: 0
Views: 482
Reputation: 488
The two previous answers helped me understand the nesting rules in XSL that I wasn't familiar with.
So here is the full XSL that does exactly what I want:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"/>
<!-- BESCHREIBUNG, BILD UND TEXT AUF "SOURCE" EBENE -->
<xsl:template match="source">
<!-- Jekyll statement --> --- <xsl:for-each select="metadata/digital_surrogate">
layout: page title: <xsl:value-of select="@filename"/> permalink: /<xsl:value-of
select="@filename"/>/ exclude: true --- </xsl:for-each>
<!-- Metadaten -->
<xsl:for-each select="metadata/source_description">
<h3>Ausstellungsort: <xsl:value-of select="@place"/></h3>
<h3>Ausstellungsdatum: <xsl:value-of select="@date"/></h3>
</xsl:for-each>
<xsl:for-each select="edition">
<h4 align="center">ediert von: <xsl:value-of select="editors/@name"/></h4>
<h4 align="center">zuletzt bearbeitet: <xsl:value-of
select="transcription_info/@last_revision_date"/></h4>
</xsl:for-each>
<br/>
<xsl:for-each select="metadata/digital_surrogate">
<xsl:variable name="urlVar">
<xsl:value-of select="@URL"/>
</xsl:variable>
<img src="{$urlVar}" valign="top"/>
</xsl:for-each>
<!-- HTML-Flex-Container für Digitalisat und Inhalt -->
<div class="flex-container">
<div>
<p>
<strong>Graphische Elemente:</strong>
</p>
<p>
Art des Siegels: <xsl:value-of select="metadata/source_description/@seal"/>
Sonstiges: <xsl:for-each select="visual_element"/>
</p>
<br/>
</div>
</div>
<hr/>
<div class="flex-container">
<div>
<p>
<strong>Transkription:</strong>
</p>
<p>
<xsl:apply-templates select="content/body/div"/>
</p>
</div>
<div>
<p>
<strong>Übersetzung:</strong>
</p>
<p>
<xsl:apply-templates select="translation"/>
</p>
<br/>
</div>
</div>
</xsl:template>
<!-- WHG LINKS AUF EBENE DIV UND TEXT -->
<xsl:template match="div">
<p>
<xsl:apply-templates select="text"/>
</p>
</xsl:template>
<xsl:template match="place">
<a href="{@link}" target="_blank">
<xsl:value-of select="."/>
</a>
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Reputation: 117175
I am guessing that instead of:
<xsl:variable name="urlPlace">
<xsl:value-of select="@link"/>
</xsl:variable>
<a href="{$urlPlace}" target="_blank"><xsl:apply-templates select="//place"/></a>
you want to do:
<a href="{@link}" target="_blank">
<xsl:value-of select="."/>
</a>
Untested, because no example to test with was provided.
--- added ---
See if you can use this as your starting point:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/source">
<html>
<body>
<xsl:apply-templates select="content/body/div"/>
</body>
</html>
</xsl:template>
<xsl:template match="div">
<p>
<xsl:apply-templates select="text"/>
</p>
</xsl:template>
<xsl:template match="place">
<a href="{@link}" target="_blank">
<xsl:value-of select="."/>
</a>
</xsl:template>
</xsl:stylesheet>
To understand this and adapt it to your needs, you will need to study XSLT's processing model: https://www.w3.org/TR/1999/REC-xslt-19991116/#section-Processing-Model
Upvotes: 2
Reputation: 167726
If you want to transform a place element like <place name="Wien" type="place_of_issue" link="http://whgazetteer.org/places/12346175/portal">Wien</place>
into an HTML a
element use a template
<xsl:template match="place">
<a href="{@link}">
<xsl:value-of select="."/>
</a>
</xsl:template>
Write templates for the transformation of other elements like the ancestors of the place
s and make sure these templates process child nodes with <xsl:apply-templates/>
.
That way the structure and order of the input should be preserved, only that you have HTML in the output reflecting the semantic XML elements you have in the input.
Upvotes: 1