在 php 中使用 xpath 创建 preg_match
creating preg_match using xpath in php
我正在尝试使用 XPATH 在 php 中获取内容。
<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);
它returns输出如下
DOMNodeList {#580
+length: 0
}
这是一个工作版本,其中包含您在评论中获得的不同建议:
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
.
对于像这样的简单任务 - 获取具有 class
属性且以 post-
开头并包含 content
的 div
节点,您应该使用常规的简单 XPath 查询:
$xp->query('//div[starts-with(@class,"post-") and contains(@class, "content")]');
在这里,
- //div
- 获取所有 div
...
- starts-with(@class,"post-")
- 具有以 "post-" 开头的 "class" 属性
- and
- 和...
- contains(@class, "content")
- 在 class
属性值中包含 "content" 子字符串。
要使用 php:functionString
,您需要注册 php
命名空间(使用 $xpath->registerNamespace("php", "http://php.net/xpath");
)和 PHP functions(注册它们都使用 $xp->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
的情况)。
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 的精彩文章。
我正在尝试使用 XPATH 在 php 中获取内容。
<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);
它returns输出如下
DOMNodeList {#580
+length: 0
}
这是一个工作版本,其中包含您在评论中获得的不同建议:
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
.
对于像这样的简单任务 - 获取具有 class
属性且以 post-
开头并包含 content
的 div
节点,您应该使用常规的简单 XPath 查询:
$xp->query('//div[starts-with(@class,"post-") and contains(@class, "content")]');
在这里,
- //div
- 获取所有 div
...
- starts-with(@class,"post-")
- 具有以 "post-" 开头的 "class" 属性
- and
- 和...
- contains(@class, "content")
- 在 class
属性值中包含 "content" 子字符串。
要使用 php:functionString
,您需要注册 php
命名空间(使用 $xpath->registerNamespace("php", "http://php.net/xpath");
)和 PHP functions(注册它们都使用 $xp->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
的情况)。
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 的精彩文章。