XSLT XML:突出显示搜索结果中的搜索词

XSLT XML:突出显示搜索结果中的搜索词,xml,xslt,Xml,Xslt,以下是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

以下是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=“kiwi”
出现以下情况时,我需要突出显示结果中的
$search
单词:

我在杂货店买了猕猴桃

你在杂货店买了猕猴桃


请帮忙

要突出显示所有出现的搜索字符串,请更改以下内容:

<xsl:template match="sentence">
    <p>
        <xsl:apply-templates/>
    </p>
</xsl:template>


致:




看一看下面的示例,它使用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)
    }
};
xquery版本“3.1”;
模块名称空间函数https://bdo.badw.de/functions';
声明函数:突出显示($element,$search){
元素{本地名称($element)}{
对于$element/node()中的$e
返回
如果($e text()的实例=true()),则
对于fn中的$match:analyze字符串($e,$search,'im'))/*
返回
如果(本地名称($match)eq‘non-match’),则
$match/text()
其他的
{$match/text()}
其他的
功能:突出显示($e,$search)
}
};

在您的示例中,搜索词
猕猴桃
单独包含在元素
水果
中(减去空格),因此它已经被标记,您可以简单地转换与搜索词匹配的任何
水果
元素(如果始终如此)。或者搜索词可以在
句子
元素中的任何地方吗?我的错!不应该在里面。我修改了XML。突出显示字符串“kiwi”相对容易。突出显示单词“kiwi”(需要定义一个单词)并不容易。我想我应该突出显示字符串,因为搜索词可以是短语或不完整的单词。谢谢Michael。“后面的子字符串”似乎不起作用。结果显示:我买了猕猴桃,你买了猕猴桃,有一个打字错误。现在试试。@michael.hor257k有没有办法做到这一点,但要使用不区分大小写的搜索字符串?@dacracot是的,有。看.@michael.hor257k不完全是我的意思,明白吗
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)
    }
};