0

是否可以使用 fn:contains 搜索 DOMDocument 对象并仅在单词的完全匹配时返回 true?

我有一个我自己没有编写的文本替换片段,它对关键字进行内部链接替换。但正如所写的那样,它也替换了部分单词,而不仅仅是完整的单词。

这是片段:

$autolinks = $this->config->get('autolinks');
if (isset($autolinks) && (strpos($this->data['description'], 'iframe') == false) 
        && (strpos($this->data['description'], 'object') == false)):
    $xdescription = mb_convert_encoding(html_entity_decode($this->data['description'], ENT_COMPAT, "UTF-8"), 'HTML-ENTITIES', "UTF-8"); 
    libxml_use_internal_errors(true);
    $dom = new DOMDocument;             
    $dom->loadHTML('<div>'.$xdescription.'</div>');             
    libxml_use_internal_errors(false);
    $xpath = new DOMXPath($dom);
    foreach ($autolinks as $autolink):
        $keyword    = $autolink['keyword'];
        $xlink  = mb_convert_encoding(html_entity_decode($autolink['link'], ENT_COMPAT, "UTF-8"), 'HTML-ENTITIES', "UTF-8");
        $target     = $autolink['target'];
        $tooltip    = isset($autolink['tooltip']);                          
        $pTexts     = $xpath->query(
            sprintf('///text()[contains(., "%s")]', $keyword)
        );
        foreach ($pTexts as $pText):
            $this->parseText($pText, $keyword, $dom, $xlink, $target, $tooltip);
        endforeach;
    endforeach;
    $this->data['description'] = $dom->saveXML($dom->documentElement);
endif;

例如:

如果我的关键字是“massage” * Massage *r 部分匹配并转换为链接,则应仅转换整个词按摩,而不是按摩器。

4

4 回答 4

3

您应该使用 fn:matches 而不是 fn:contains。这允许您使用正则表达式进行匹配。然后你可以用 \b 包含单词边界。

sprintf('///text()[matches(., "\b%s\b")]', $keyword)

请注意,这不会影响您的函数 parseText 正在执行的任何操作。因此,虽然<Tagname>This is a sentence containing the word massager.</Tagname>不会受到影响,但我不保证会发生什么<Tagname>The massager give the customer a massage.</Tagname>。为确保正确处理,您的 parsetext 函数将需要修改。可能以与上述类似的方式。

另请注意,您可能需要对 parsetext 进行的修改意味着上述更改变得不必要。

于 2013-09-11T09:01:40.307 回答
1

XSLT 1.0 中的文本操作非常有限,但如果您不能迁移到 2.0(为什么不呢?),那么translate()通常会派上用场。用于translate()将所有常见的标点字符替换为空格,用于concat()在前后添加空格,然后进行测试contains(' massage ')(注意空格)。

于 2013-09-11T09:04:51.213 回答
1

matches(),ends-with()不受支持时,您可以使用starts-with()string-length()来绕过。

例子:

[starts-with(.,'$var') and string-length(.)=string-length('$var')]

这相当于matches()

于 2016-05-17T01:58:06.670 回答
0

这实际上非常简单,我只是在$keyword变量的末尾添加了一个空格,所以现在它只在找到整个单词时才返回 true。

foreach ($autolinks as $autolink):
    $keyword    = trim($autolink['keyword']) . ' ';
    $xlink      = mb_convert_encoding(html_entity_decode($autolink['link'], ENT_COMPAT, "UTF-8"), 'HTML-ENTITIES', "UTF-8");
    $target     = $autolink['target'];
    $tooltip    = isset($autolink['tooltip']);                          
    $pTexts     = $xpath->query(
        sprintf('///text()[contains(., "%s")]', $keyword)
    );
    foreach ($pTexts as $pText):
        $this->parseText($pText, $keyword, $dom, $xlink, $target, $tooltip);
    endforeach;
endforeach;

感谢所有试图提供帮助的人。

于 2013-09-11T10:15:55.147 回答