19

这是 Javascript 中的有效 XPath:

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

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

//*[@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(@Dimitre Novatchev 在评论中提到这一点,但忽略了重要性),则有效的 Javascript XPath 查询在 PHP 中可以正常工作。不幸的是,我无法控制输入 DTD,所以现在我必须研究一种方法来克服这个问题,或者找到一个即使没有有效 DTD 也能工作的解决方案。

4

3 回答 3

7

只是看到 Salathe 实际上回答了同样的问题,但考虑到您的评论并更加强调这一点:

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

警告: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 将所有 HTMLid属性标记为 xpath 的 ID:

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

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

于 2012-08-05T19:19:31.797 回答
0

这不是一个完整的答案,但它太大而无法作为评论发表,它可能会对您有所帮助。

如果您可以控制输入 XML,那么id您可以在 XML 文档本身中通过在id属性前面加上xml:.

例如,如果您有 XML

<foo id="x27"/>

并将其更改为

<foo xml:id="x27"/>

那么 id() 函数会将该属性识别为正式的 XMLid类型,而不仅仅是带有 name 的属性id

我知道这个“技巧”适用于 Saxon 处理器,但我必须承认我没有在 PHP 上尝试过。

W3C xml:id

于 2012-08-08T23:46:09.837 回答
0

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

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

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

示例代码

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

于 2012-08-07T13:23:41.317 回答