这是xml:
<?xml version="1.0" encoding="UTF-8"?>
<file>
<text>
<p>
<sentence>I bought kiwi at the grocery store.</sentence>
<sentence>I also bought bananas at the store.</sentence>
<sentence>Then, I bought a basket at another store.</sentence>
</p>
<p>
<sentence>You bought kiwi at the grocery store.</sentence>
<sentence>You also bought bananas at the store.</sentence>
<sentence>Then, You bought a basket at another store.</sentence>
</p>
</text>
</file>
这是XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="sentence">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates select="file/text/p/sentence[contains(.,$search)]"/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
我需要在$search
时突出显示结果中的$search="kiwi"
字词:
我在杂货店买了<mark>
奇异果</mark>
。
你在杂货店买了<mark>
奇异果</mark>
。
请帮忙!
答案 0 :(得分:3)
要突出显示搜索字符串的所有匹配项,请更改此项:
<xsl:template match="sentence">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
为:
<xsl:template match="sentence">
<p>
<xsl:call-template name="hilite">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="search-string" select="$search"/>
</xsl:call-template>
</p>
</xsl:template>
<xsl:template name="hilite">
<xsl:param name="text"/>
<xsl:param name="search-string"/>
<xsl:choose>
<xsl:when test="contains($text, $search-string)">
<xsl:value-of select="substring-before($text, $search-string)"/>
<mark>
<xsl:value-of select="$search-string"/>
</mark>
<xsl:call-template name="hilite">
<xsl:with-param name="text" select="substring-after($text, $search-string)"/>
<xsl:with-param name="search-string" select="$search-string"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
答案 1 :(得分:0)
看看下面的示例,该示例使用XPath 3.0 fn:analyze-string()在我看来比 xsl:analyze-string 更好,并且效果很好与Saxon 9.8 HE。我也首先尝试了michael的解决方案,但是在我的用例中它无法正常工作。
它也应该在子节点上工作,而不会破坏层次结构或松开尾巴。
<xsl:template name="highlight">
<xsl:param name="element"/>
<xsl:param name="search" as="xs:string"/>
<xsl:param name="flags" required="no" select="'im'" as="xs:string"/>
<xsl:choose>
<xsl:when test="empty($search) or $search eq ''">
<xsl:value-of select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="$element/node()">
<xsl:choose>
<xsl:when test=". instance of text()">
<xsl:for-each select="fn:analyze-string(., $search, $flags)/*">
<xsl:choose>
<xsl:when test="local-name(.) eq 'non-match'">
<xsl:value-of select="./text()"/>
</xsl:when>
<xsl:otherwise>
<span class="highlighted">
<xsl:value-of select="./text()"/>
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="highlight">
<xsl:with-param name="element" select="."/>
<xsl:with-param name="search" select="$search"/>
<xsl:with-param name="flags" select="$flags"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
仅针对xQuery,请参见:
xquery version "3.1";
module namespace functions = 'https://bdo.badw.de/functions';
declare function functions:highlight($element, $search) {
element {local-name($element)} {
for $e in $element/node()
return
if ($e instance of text() = true()) then
for $match in fn:analyze-string($e, $search, 'im')/*
return
if (local-name($match) eq 'non-match') then
$match/text()
else
<span class="highlighted">{$match/text()}</span>
else
functions:highlight($e, $search)
}
};