在有效的 PHP query() XPath | 中转换 Javascript XPath规范化 JS XPath --> PHP

2022-08-30 21:20:19

这是Javascript中有效的XPath:

id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]

这变成了有效的PHP XPath,可以与DOMXPath->query()一起使用

//*[@id="priceInfo"]//div[@class="standardProdPricingGroup"]//span[1]
  1. 您是否知道任何已经执行此转换的库或自定义组件?
  2. 您知道列出两种语法差异的现有文档吗?

我主要担心的是可能有很多差异,我希望识别这些差异,并且我在识别这些差异方面遇到了问题。

这个问题也可以以不同的方式提出:由于Javascript可以具有不同的有效XPath格式,因此如何规范化它们以使用PHP。

其中一个更新还提到,如果存在包含此定义的有效 DTD,则 id() 函数是有效的 XPath。我对输入DTD没有权力,如果有一种方法可以找到一个没有任何特定DTD的解决方案,那就太好了。

更新:

我想用算法将第一种格式转换为第二种格式。我的输入是第一个,而不是第二个。无法更改此内容。

正如@Nison Maël所指出的那样,第二种格式是有效的Javascript XPath,如下所示:不幸的是,http://jsbin.com/elatum/2/edit 这只会增加Javascript XPath“碎片化”的问题。

@salathe指出,如果记录的输入具有有效的DTD,则有效的Javascript XPath查询在PHP中工作正常(@Dimitre Novatchev在评论中提到了这一点,但忽略了重要性)。不幸的是,我无法控制输入DTD,所以现在我必须研究一种方法来克服这个问题,或者找到一个即使没有有效的DTD也能工作的解决方案。


答案 1

只是看到Salathe实际上回答了相同的答案,但是考虑到您的评论并进一步强调这一点:

您不需要指定任何 DTD。只要使用 or 函数,HTML 属性实际上就为 xpath 函数注册。使用 http://jsbin.com/elatum/2/edit 中给出的演示HTML,您甚至在加载文档时收到错误:DOMDocument::loadHTMLDOMDocument::loadHTMLFileidid()

警告: DOMDocument::loadHTMLFile(): ID priceInfo 已经在 ...

这已经表明这是一个真正的ID属性,因为它抱怨重复。相关的示例代码如下所示:

$xpath = 'id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]';

$doc = new DOMDocument();
$doc->loadHTMLFile(__DIR__ . '/../data/file-11796340.html');
$xp = new DOMXPath($doc);

$r = $xp->query($xpath);
echo $xpath, "\n";
echo $r ? $r->length : 0, ' elements found', "\n";
if (!$r) return;
foreach($r as $node) {
    echo " - ", $node->nodeValue, "\n";
}

输出为:

id("priceInfo")/div[@class="standardProdPricingGroup"]/span[1]
1 elements found
 - hello

如果您需要更多控制,请先运行 xpath 以将所有 HTML 属性标记为 xpath 的 ID:id

$r = $xp->query("//*[@id]");
if ($r) foreach($r as $node) {
    $node->setIdAttribute('id', true);
}

然后,您可以对函数使用相同的 xpath,而无需更改它。id()


答案 2

你不能在表达的开头就翻译成吗?id("...")//*[@id="..."][1]

例如,如果可以假设表达式中没有任何括号:id(...)

$queryRewritten =   preg_replace('/^id\(([^\)]+)\)/','//*[@id=$1][1]',$query);

示例代码

编辑:更正了替换,id() imust 是表达式中的第一个