【问题标题】:XSLT 2.0 trimming text length of final HTML outputXSLT 2.0 修剪最终 HTML 输出的文本长度
【发布时间】:2018-11-17 16:42:58
【问题描述】:

这里是 XSLT 小提琴:https://xsltfiddle.liberty-development.net/bFDb2Dh/2

在 XSL 2.0 中,我从 eXist-db Lucene 搜索函数接收到一小组节点,该函数返回原始 XML,但将搜索词包装在 <exist:match/> 中。所以我搜索tei:seg 并得到以下信息(我将输出包装在一个额外的元素中以供以后处理需要):

<doc>
  <url>http://localhost:8081/exist/apps/deheresi/doc/MS609-0454</url>
  <seg xmlns="http://www.tei-c.org/ns/1.0" type="dep_event" subtype="event" xml:id="MS609-0454-2" corresp="#MS609-0453-7">Item. Dixit<lb break="y" n="11"/>quod 
    <persName nymRef="#abbot_of_Saint_Papoul" role="npar">abbas de 
        <placeName nymRef="#Saint-Papoul_Aude">Sancto Papulo</placeName>
    </persName> ceperat 
    <persName nymRef="#heretics_not_named" role="par">duos hereticos</persName> et 
    <persName nymRef="#Arnald_Savauza_SML-AU" ana="#pFreeHer" role="par">Arnaldus de Savauza</persName> volebat manulevare dictos hereticos. Et rogavit 
    ipsum<lb break="y" n="12"/>testim et 
    <persName nymRef="#Arnald_Forner_SML-AU" ana="#pFreeHer" role="par">Arnaldum Fornier</persName> et 
    <persName nymRef="#Raimund_Forner_SML-AU" ana="#pFreeHer" role="par">Raimundum Fornier</persName>, fratres,  
    quod irent cum eo 
    ad abbatem de <placeName type="event_loc" nymRef="#Saint-Papoul_Abbey">Sancto<lb break="y" n="14"/>Papulo</placeName> 
    et manulevarent hereticos. Et dictus 
    <persName nymRef="#Arnald_Savauza_SML-AU" ana="#pFreeHer" role="ref">Arnaldus de Savauza</persName> 
    dixit quod dictus abbas promiserat ei quod redderet sibi dictos<lb break="y" n="15"/>
    hereticos pro mille <exist:match xmlns:exist="http://exist.sourceforge.net/NS/exist">solidis</exist:match> tholosanis. Et 
    <persName nymRef="#Bernard_Alzeu_SML-AU" ana="#pFreeHer" role="ref">Bernardus Alzeus</persName> et 
    <persName nymRef="#Ysarn_de_Gibel_SML-AU" ana="#pFreeHer" role="ref">Ysarnus de Gibel</persName> portabant illos denarios. 
    Sed non potuerunt dictos hereticos ma<lb break="n" n="16"/>nulevare. 
    <date type="event_date" when="1237">Et sunt anni VIIIor vel circa.</date>
  </seg>
</doc>

在 XSLT 中,我通过一些转换将其输出为 HTML。但是,输出如下所示:

<td>Item. Dixit quod 
   abbas de 
   Sancto Papulo
   ceperat 
   duos hereticos et 
   Arnaldus de Savauza volebat manulevare dictos hereticos. Et rogavit 
   ipsum testim et 
   Arnaldum Fornier et 
   Raimundum Fornier, fratres,  
   quod irent cum eo 
   ad abbatem de Sancto Papulo 
   et manulevarent hereticos. Et dictus 
   Arnaldus de Savauza 
   dixit quod dictus abbas promiserat ei quod redderet sibi dictos 
   hereticos pro mille <span class="search-hit">
   <a href="http://localhost:8081/exist/apps/deheresi/doc/MS609-0454"> 
   solidis</a></span> tholosanis. Et 
   Bernardus Alzeus et 
   Ysarnus de Gibel portabant illos denarios. 
   Sed non potuerunt dictos hereticos manulevare. 
   Et sunt anni VIIIor vel circa.
</td>

但我想用省略号缩短最终输出:

<td>...dictus abbas 
  promiserat ei quod redderet sibi dictos 
  hereticos pro mille <span class="search-hit"><a 
  href="http://localhost:8081/exist/apps/deheresi/doc/MS609-0454"> 
  solidis</a></span> tholosanis. Et 
  Bernardus Alzeus et 
  Ysarnus de Gibel portabant illos...
</td>

&lt;span class="search-hit"/&gt; 内容两侧的文本输出限制为x 字符数。 (进一步,如果可能,应用normalize-space() 来清理原始文档中的字符间距问题。)

我还没有找到任何想法如何在当前的 XSL 转换中解决这个问题,仅在后处理中。

非常感谢。

【问题讨论】:

  • 由于您拥有的 XML 具有许多不同元素中的结果文本,并且当前结果是通过将 XML 推送到几个模板来产生的,我不知道如何修复原始 XSLT,除了将当前结果存储在一个变量中并通过不同的模式运行它,然后根据需要进行规范化和修剪。我不确定这是否已经是您所做的后处理类型。至于修剪的算法,每个td里面有一个span class="search-hit"吗?
  • 是的,每个输出 td 只有一个 span class="search-hit"
  • 我还要补充一点,td 内永远不会有任何其他元素 - 这是搜索结果的最终目标输出结构。
  • 我已尝试将原始方法的结果存储在与tei:seg xsltfiddle.liberty-development.net/bFDb2Dh/3 匹配的模板的变量中,然后您可以将其推送到不同的模式并进行任何规范化和修剪和两个文本节点。那里的结果看起来并不漂亮,但我想如果您知道要修剪或删除空格的算法,那么在文本节点的两个模板中使用replace 和/或xsl:analyze-string 对其进行微调应该很容易。
  • seg 模板中分配变量是一个非常有趣的解决方案,谢谢。如果您想将此作为答案发布,我会接受。

标签: xslt xslt-2.0


【解决方案1】:

您可以将从现有代码中获得的 tei:segtd 结果分别存储在变量中

<xsl:template match="tei:seg">
    <xsl:variable name="search-hit">
        <xsl:apply-templates/>
    </xsl:variable>
    <td>
        <xsl:apply-templates select="$search-hit" mode="trim"/>
    </td>
</xsl:template>

然后您可以通过不同的模式推送该内容,该模式具有文本节点的模板以进行修剪:

<xsl:param name="trim-to" as="xs:integer" select="60"/>

<xsl:template match="text()[1]" mode="trim">
    <xsl:variable name="normalized" as="xs:string" select="normalize-space(.)"/>
    <xsl:value-of select="concat('...', substring($normalized, string-length($normalized) - $trim-to))"/>
</xsl:template>

<xsl:template match="text()[last()]" mode="trim">
    <xsl:variable name="normalized" as="xs:string" select="normalize-space(.)"/>
    <xsl:value-of select="concat(substring($normalized, 1, $trim-to), '...')"/>
</xsl:template>

<xsl:template match="span[@class = 'search-hit']" mode="trim">
    <xsl:copy-of select="."/>
</xsl:template>

可以使用文本节点模板中的replace 和/或tokenize 和/或xsl:analyze-string 对执行修剪/规范化的代码进行微调,但这只有在修剪所需的算法明确时才有可能.

小提琴在https://xsltfiddle.liberty-development.net/bFDb2Dh/3处调整。

【讨论】:

  • 在部署它时,我意识到&lt;span class="search-hit"&gt; 可能出现在td 的开头或结尾,因此模板text()[1]text()[last()] 将是相同的 -这导致ambiguous rule match。有没有办法让这些模板相对于跨度之前/之后的文本节点而不是绝对位置?我尝试使用以下/前面的兄弟姐妹,但似乎找不到正确的 XPath 公式来击中文本节点....
  • 您可以尝试使用match="text()[following-sibling::node()[1][self::span[@class = 'search-hit']]]" 获取text()[1]match="text()[preceding-sibling::node()[1][self::span[@class = 'search-hit']]]" 获取text()[last()]。如果只创建了那个特定的span,则不确定是否需要span 上的谓词,但使用following-sibling::node()[1][self::foo] 进行检查是表达直接foo 兄弟的常用方式。
猜你喜欢
  • 1970-01-01
  • 2013-07-09
  • 1970-01-01
  • 2018-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
相关资源
最近更新 更多