试图确定是否有任何P标签文本完全在强标签/ B标签之内
// Match (unacceptable, flag to user):
<p><strong>Any text and <span>maybe</span> other <em>tags</em></strong></p>
// Don't match (acceptable):
<p>Any text and <strong>maybe</strong> other <em>tags</em></p>
答案 0 :(得分:1)
p
... //p
strong
后代节点... //p[.//strong]
//p[.//strong[normalize-space(.) != ""]]
,并且没有文本节点的后代,其内容没有strong
祖先节点:
//p[
.//strong[normalize-space(.) != ""] and
not(.//text()[normalize-space(.) != "" and not(ancestor::strong)])
]
这将检查两个条件。首先,该段落的某些实际内容位于strong
内,而没有实际的内容不在strong
内-换句话说,单词内容的格式不同。
示例:
$html = <<<'HTML'
<p><strong>Any text and <span>maybe</span> other <em>tags</em></strong></p>
<p>Any text and <strong>maybe</strong> other <em>tags</em></p>
<p><strong>Builder's</strong> <strong>tea</strong></p>
<p><em><strong>Builder's</strong> <strong> tea</strong></em></p>
HTML;
$document = new DOMDocument();
$document->loadHTML($html);
$xpath = new DOMXpath($document);
$expression =
'//p[
.//strong[normalize-space(.) != ""] and
not(.//text()[normalize-space(.) != "" and not(ancestor::strong)])
]';
foreach ($xpath->evaluate($expression) as $p) {
var_dump(
$document->saveXml($p)
);
}
输出:
string(75) "<p><strong>Any text and <span>maybe</span> other <em>tags</em></strong></p>"
string(54) "<p><strong>Builder's</strong> <strong>tea</strong></p>"
string(64) "<p><em><strong>Builder's</strong> <strong> tea</strong></em></p>"
表达式也可以扩展为涵盖b
:
//p[
(
.//strong[normalize-space(.) != ""] or
.//b[normalize-space(.) != ""]
) and
not(
.//text()[
normalize-space(.) != "" and
not(ancestor::*[self::strong or self::b])
]
)
]
答案 1 :(得分:0)
以下代码检查P标签在任何Strong标签之前和之后是否不包含文本或其他HTML标签,从而确定P标签完全是粗体(强)。
$false_headings = $xpath->query("//p/strong");
foreach ($false_headings as $heading) {
if ($heading->previousSibling === null and $heading->nextSibling === null) {
// Report to user
break;
}
}
答案 2 :(得分:0)
这是一种方法,部分基于@gangabass的建议。它计算仅包含单个<p>
元素的<strong>
元素,这些元素可选地仅由空白文本包围。
$unacceptableNodesCount = $xpath->evaluate( 'count(//p[count(*) = 1 and name(*) = "strong" and normalize-space() = string(strong)])' );
var_dump( $unacceptableNodesCount );
但是,老实说,如果目标是防止用户仅使用粗体文本并且确定了用户,则他们可能会找到一种方法。例如,将<strong>
元素用Unicode空格字符或类似的字符括起来。
答案 3 :(得分:0)
您的问题描述表明您也想抓住
<p><strong>Builder's</strong><strong> tea</strong></p>
也许还有
<p><strong>Builder's</strong> <strong>tea</strong></p>
其中一些建议的解决方案没有解决此问题。
但是不清楚您是否还想捉住
<p><emph><strong>Builder's</strong> <strong> tea</strong></emph></p>
我认为XPath 2.0中与“任何P标签文本完全在强/ B标签内”最接近的是
//p[empty(.//text()[normalize-space()] except .//strong//text()])]
选择所有不具有非白色后代文本节点的p个元素,该节点不是p中强元素的后代。
我无法立即在XPath 1.0中看到实现此目的的方法,但是我的XPath 1.0十分生锈。