【问题标题】:creating preg_match using xpath in php在 php 中使用 xpath 创建 preg_match
【发布时间】:2016-01-29 07:12:32
【问题描述】:

我正在尝试在 php 中使用 XPATH 获取内容。

<div class='post-body entry-content' id='post-body-37'>
<div style="text-align: left;">
<div style="text-align: center;">
Hi
</div></div></div>

我正在使用下面的 php 代码来获取输出。

 $dom = new DOMDocument;
 libxml_use_internal_errors(true);
 $dom->loadHTML($html);
 $xpath = new DOMXPath($dom);
 $xpath->registerPhpFunctions('preg_match');
 $regex = 'post-(content|[a-z]+)';
 $items = $xpath->query("div[ php:functionString('preg_match', '$regex', @class) > 0]");
 dd($items);

它返回如下输出

DOMNodeList {#580 
+length: 0 
} 

【问题讨论】:

  • 不应该分隔正则表达式吗?试试$regex = '/post-(content|[a-z]+)/';
  • 对不起,我的错字了。我用 $regex = '/post-(content|[a-z]+)/';在代码中
  • this demo,你不需要正则表达式。
  • 是的。但我正在寻找以 post- 开头并包含 content* 的课程。正如我在上面的代码中提到的,我使用上面的正则表达式,因为有些将具有
    和一些将具有
    。我需要解析这两个选项。如果你看第一个,它包含两个类*post-body entry-content,如果你看第二个,它只包含一个类**post-conten。我也需要度过难关。

标签: php regex dom xpath domxpath


【解决方案1】:

这是一个工作版本,其中包含您在 cmets 中获得的不同建议:

libxml_use_internal_errors(true);

$dom = new DOMDocument;
$dom->loadHTML($html);

$xpath = new DOMXPath($dom);
// you need to register the namespace "php" to make it available in the query
$xpath->registerNamespace("php", "http://php.net/xpath"); 
$xpath->registerPhpFunctions('preg_match');

// add delimiters to your pattern
$regex = '~post-(content|[a-z]+)~';

// search your node anywhere in the DOM tree with "//"
$items = $xpath->query("//div[php:functionString('preg_match', '$regex', @class)>0]");

var_dump($items);

显然,这种模式是没有用的,因为您可以使用可用的 XPATH 字符串函数(如 contains)获得相同的结果。

【讨论】:

    【解决方案2】:

    对于像这样的简单任务 - 获取具有以 post- 开头并包含 contentclass 属性的 div 节点,您应该使用常规的简单 XPath 查询:

    $xp->query('//div[starts-with(@class,"post-") and contains(@class, "content")]');
    

    这里, - //div - 得到所有的divs... - starts-with(@class,"post-") - 具有以“post-”开头的“class”属性 - and - 和... - contains(@class, "content") - 在class 属性值中包含“内容”子字符串。

    要使用php:functionString,您需要注册php 命名空间(使用$xpath-&gt;registerNamespace("php", "http://php.net/xpath");)和PHP functions(要注册它们都使用$xp-&gt;registerPHPFunctions();)。

    对于复杂的场景,当您需要更深入地分析值时,您可能需要创建并注册自己的函数:

    function example($attr) {
        return preg_match('/post-(content|[a-z]+)/i', $attr) > 0;
    }
    

    然后在 XPath 内部:

    $divs = $xp->query("//div[php:functionString('example', @class)]");
    

    这里,functionString@class 属性的字符串内容传递给example 函数,而不是对象(就像php:function 的情况一样)。

    IDEONE demo:

    function example($attr) {
        return preg_match('/post-(content|[a-z]+)/i', $attr) > 0;
    }
    $html = <<<HTML
    <body>
    <div class='post-body entry-content' id='post-body-37'>
    <div style="text-align: left;">
    <div style="text-align: center;">
    Hi
    </div></div></div>
    </body>
    HTML;
    $dom = new DOMDocument;
    $dom->loadHTML($html, LIBXML_HTML_NOIMPLIED|LIBXML_HTML_NODEFDTD);
    
    $xp = new DOMXPath($dom);
    $xp->registerNamespace("php", "http://php.net/xpath");
    $xp->registerPHPFunctions('example');
    $divs = $xp->query("//div[php:functionString('example', @class)]");
    foreach ($divs as $div) {
        echo $div->nodeValue;    
    }
    

    另请参阅Using PHP Functions in XPath Expressions 中有关在 XPath 中使用 PhpFunctions 的精彩文章。

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签