XPath包含()搜索完全匹配

时间:2013-09-11 08:00:32

标签: php regex xpath

是否可以使用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;

例如:

如果我的关键字是“按摩”* 按摩 * r部分匹配并转换为链接,只需要转换整个单词按摩,而不是按摩器。

4 个答案:

答案 0 :(得分: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进行的修改意味着上述更改变得不必要。

答案 1 :(得分:1)

XSLT 1.0中的文本操作非常有限,但是如果你不能移动到2.0(为什么不移动?)那么translate()经常会得到解决。使用translate()按空格替换所有常见标点符号,使用concat()添加前后空格,然后测试contains(' massage ')(注意空格)。

答案 2 :(得分:1)

如果不支持ends-with()starts-with(),您可以使用string-length()[starts-with(.,'$var') and string-length(.)=string-length('$var')] 来解决问题。

示例:

matches()

这相当于{{1}}。

答案 3 :(得分: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;

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