使用 XSLT 为 XML 到 HTML 转换中的不同 <place> 标记添加超链接

Posted

技术标签:

【中文标题】使用 XSLT 为 XML 到 HTML 转换中的不同 <place> 标记添加超链接【英文标题】:Add hyperlinks for different <place> tags in XML to HTML transformation with XSLT 【发布时间】:2021-09-26 03:15:14 【问题描述】:

我有一组 XML 文件,其中地名(在不同的历史拼写中)被标记为 &lt;place&gt;:参见。 sample file。 place 标签还包含属性link,其值是指向世界历史地名词典页面的超链接,例如:

<place name="Wien" type="place_of_issue"
      link="http://whgazetteer.org/places/12346175/portal">Wien</place>

使用 XSLT 将 XML 文件转换为 html,我希望将文本中的每个此类标记替换为超链接 &lt;a href&gt;,链接到相同的 WHG URL。

基于Michael Hor-257k 答案的我的 XSL 的最小版本是:

   <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>

这至少正确地显示了以正确顺序提及的所有地名,带有正确的 WHG 链接和正确的名称:

<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>

但是,链接仍然显示在转录下方,而不是内部。

我想要的 HTML 输出是:

<div class="flex-container">
   <div>
      <p><strong>Transkription:</strong></p>
      <p>
              Wir Vorsteher und gesamte
         Meister des ehrsamen Handwerks der b&uuml;rgerl:[ichen] Tischlern in der K:[aiserlich]
              K:[&ouml;niglichen] Haubt = und Residenz Stadt <a href="http://whgazetteer.org/places/12346175/portal" target="_blank">Wien</a> (beglaubigen) hiermit,
              da&szlig; gegenwertiger Tischlergesell, Namens Georg
              Gramer von <a href="http://whgazetteer.org/places/13067462/portal" target="_blank">Maintz</a> - -
[etc.]
</p>
</div>
</div>

【问题讨论】:

1.请发布minimal reproducible example。 2、你知道//是什么意思吗? 示例文件链接:github.com/ieg-dhr/DigitaleEditorikDMGK/blob/main/… 【参考方案1】:

前面的两个答案帮助我理解了我不熟悉的 XSL 中的嵌套规则。

所以这是完全符合我要求的完整 XSL:

<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>

【讨论】:

【参考方案2】:

我猜不是:

                <xsl:variable name="urlPlace">
                    <xsl:value-of select="@link"/>
                </xsl:variable>
                <a href="$urlPlace" target="_blank"><xsl:apply-templates select="//place"/></a>

你想做什么:

                <a href="@link" target="_blank">
                    <xsl:value-of select="."/>
                </a>

未经测试,因为没有提供用于测试的示例。


--- 已添加 ---

看看你是否可以以此为起点:

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>

要理解这一点并使其适应您的需求,您需要研究 XSLT 的处理模型:https://www.w3.org/TR/1999/REC-xslt-19991116/#section-Processing-Model

【讨论】:

感谢您的建议。即使我添加了 place 的 XPath,这也会在我的转录底部生成一个带有 now 值的超链接。 我得到了不同的结果:xsltfiddle.liberty-development.net/asoTKf。而且我还是不知道你想要什么结果。 我希望链接出现在转录中的原始位置标签所在的位置,而不是我从div标签中提取的转录的底部。 我想知道是否可以将您的解决方案定义为一个变量来替换转录中的每个place 标签。 恐怕您正在尝试在没有足够背景的情况下做某事(或者在我看来)。我已经发布了我的答案,但您还有更多工作要做。【参考方案3】:

如果您想将 &lt;place name="Wien" type="place_of_issue" link="http://whgazetteer.org/places/12346175/portal"&gt;Wien&lt;/place&gt; 这样的 place 元素转换为 HTML a 元素,请使用模板

<xsl:template match="place">
  <a href="@link">
    <xsl:value-of select="."/>
  </a>
</xsl:template>

为转换其他元素(如places 的祖先)编写模板,并确保这些模板处理带有&lt;xsl:apply-templates/&gt; 的子节点。

这样应该保留输入的结构和顺序,只是输出中的 HTML 反映了输入中的语义 XML 元素。

【讨论】:

以上是关于使用 XSLT 为 XML 到 HTML 转换中的不同 <place> 标记添加超链接的主要内容,如果未能解决你的问题,请参考以下文章

xslt 生成的表中的 URL 重定向到该页面

防止 xslt 将 xml 转换为 html

XHTML 到 XML XSLT 的转换

XSLT 转换从混合内容中删除 HTML 元素

XSLT XML 到 HTML 的 2 阶段转换 - 必须是更好的方法

CSS 转换不起作用 Firefox for XML 文档使用 XSLT 转换为 HTML