xslt - XPath 有序优先属性搜索

标签 xslt search xpath attributes

我想编写一个 XPath,它可以在 HTML DOM 上返回一些链接元素。

语法是错误的,但这是我想要的要点:

//web:link[@text='Login' THEN_TRY @href='login.php' THEN_TRY @index=0]

THEN_TRY 是一个虚构的运算符,因为我找不到要使用的运算符。如果页面上存在多个给定 [attribute=name] 对组的链接,则应返回与最左侧属性匹配的链接而不是其他任何链接。

例如,考虑上面的示例 XPath 找到 3 个与任何给定属性匹配的链接的情况:
link A: text='Sign In', href='Login.php', index=0
link B: text='Login', href='Signin.php', index=15
link C: text='Login', href='Login.php', index=22

链接 C 被列为最佳匹配,因为它匹配 First 和 Second 属性。

Link B 排名第二,因为它只匹配 First 属性。

链接 A 排名最后,因为它与 First 属性不匹配;它只匹配第二个和第三个属性。

XPath 应该返回最佳匹配,链接 C。

如果多个链接与“最佳匹配”相关联,则 XPath 应返回它在页面上找到的第一个最佳链接。

最佳答案

有一个蛮力解决方案。我将演示两个属性而不是三个。

(
//web:link[@text != 'Login' 和 @href != 'Login.php'
而不是(//web:link[@text = 'Login' or @href = 'Login.php'])]
|//web:link[@text != 'Login' and @href = 'Login.php'
而不是(//web:link[@text = '登录'])]
|//web:link[@text = 'Login' and @href != 'Login.php'
而不是(//web:link[@text = 'Login' and @href = 'Login.php'])]
|//web:link[@text = 'Login' and @href = 'Login.php']
)[1]

也就是说,选择两个属性都不匹配的所有链接,但前提是没有更匹配的链接。然后选择所有具有较小属性匹配的链接,但仅当没有具有较高属性匹配的链接时。只有第一个属性匹配的选择链接,但前提是没有两个属性都匹配的链接。然后选择两个属性匹配的链接。这四个连接词中只有一个是非空的,因此“| ”运算符实际上从未组合任何东西。最后,按文档顺序选择第一个链接,以防这些节点集中的任何一个具有多个元素。

我只做两个属性而不是三个的原因是因为我不想输入所有八个案例。如果您对任何链接都不感兴趣,则可以省略第一种情况,除非至少有一个属性匹配。

在这种情况下,您最好选择 the much simpler query Jeff showed 中的所有候选人。 ,然后使用其他代码对结果进行排名,您可以更轻松地使用迭代和变量来选择最佳候选者。

如果您可以使用 XPath 2 ,那么您可以使用 the comma operator (或 the concat function )加入节点序列(取代节点集)。试试这个,例如:

(
//web:link[@text = 'Login' and @href = 'Login.php' and @index = 0]
,//web:link[@text = 'Login' and @href = 'Login.php' and @index != 0]
,//web:link[@text = 'Login' and @href != 'Login.php' and @index = 0]
,//web:link[@text = 'Login' and @href != 'Login.php' and @index != 0]
,//web:link[@text != 'Login' and @href = 'Login.php' and @index = 0]
,//web:link[@text != 'Login' and @href = 'Login.php' and @index != 0]
,//web:link[@text != 'Login' and @href != 'Login.php' and @index = 0]
,//web:link[@text != 'Login' and @href != 'Login.php' and @index != 0]
)[1]


顺便说一句,这里有一个简单的方法来为每个链接分配一个等级,这使得比较它们变得非常简单。想象一个位域,您要检查的每个属性都有一个位。如果第一个属性匹配,则设置最左边的位,否则不设置。如果第二个属性匹配,则设置下一个最高有效位等。因此,对于您的示例,您将获得以下位值:

011 链接 A: text='登录', href='Login.php', index=0
100 链接 B: text='Login', href='Signin.php', index=15
110 链接 C: text='Login', href='Login.php', index=22

要选择最佳匹配,请将位字段视为二进制数。链接 A 的得分为 3,链接 B 的得分为 4,链接 C 的得分为 6。(这有点让人想起 specificity of CSS selectors 的确定方式。)这是一种对排序标准进行建模的方法,但是现在我已经把它全部输入了,我不太明白它会导致 XPath 中的任何简洁的解决方案。

关于xslt - XPath 有序优先属性搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/774585/

相关文章:

php - 如何使用 PHP 从 HTML 文档中仅提取某些标签?

XSLT 合并/合并节点

java - 仅当源中存在值时才创建标签

java - 在已部署的 Apache 6.0 中转换 XML 时可能出现的错误

xml - 使用 JAXP API 运行已编译的 Saxon 样式表

php - in_array 问题

django - 使用内置全文搜索的 django postgres 通过特定列进行全文搜索

mysql - 将 WHERE 子句与 LIKE 和 OR 一起使用

xpath - Groovy GPath 编译器中是否有 XPath?

python - 为什么在使用 lxml(在 python 中)处理 XHTML 文档时 xpath 不起作用?