识别 css 选择器字符串与 XPath 字符串



我正在为html开发一个小的查询模块(在js中),我想提供一个通用的query(selector)函数,支持css选择器和XPath选择器作为字符串参数。

无论每种选择是如何完成的,我在这里的问题是如何识别给定的字符串是 xpath 还是 css 选择器。我们可以假设该函数是这样的:


function query(selector){
selectorKind = identifySelectorKind(selector); // I want to know how to code this particular function
if(selectorKind==="css") return queryCss(selector);
if(selectorKind==="xPath") return queryXPath(selector); //Assume both functions exists and work
}

我的第一个方法(鉴于我对 xPath 查询的了解有限)是通过检查第一个字符是否/来识别查询类型(这里我假设所有相关的 xPath 查询都以/开头)

所以,identifySelectorKind会有点像这样:

function identifySelectorKind(selector){
if (selector[0] === "/") return "xPath";
else return "css";
}

请注意,我不需要验证 css 和 xpath 选择器,我只需要一种明确的方式来区分它们。这个逻辑就够了吗?(换句话说,所有 xPath 选择器都以/开头,没有 css 选择器以相同的方式开始?),如果没有,是否有更好的方法或我可能想知道的一些注意事项?

你不一定。例如,*是有效的 xpath 和有效的 css 选择器,但它匹配每个元素中的一组不同的元素。

如果您绝对确定您的 XPath 选择器将始终以/开头,那么是的,这很好。请注意,XPath 选择器不必以/开头,但如果你的选择器总是从根目录选择,那就没问题了。

当然,仅搜索/是不够的!

示例 CSS 选择器(这将是误报):
nav [itemtype="https://schema.org/BreadcrumbList"]

我还在编写一个实用程序函数来使用 querySelector 或 xpath,并且需要区分 2。

这里的问题是两种语法都可以包含任意字符串:
xpath: //*[contains(text(),"string")]
css: *[some-attr="string"]

。因此,无论您使用什么字符来描述,在这两种语法中,总是有可能的。(css 中的 xpath 字符串是有效的,因此 xpath 中的 css 字符串是有效的):
xpath: //*[contains(text(),"a:hover:not(xpath)")]
css: *[xpath-attr="fuuu/xpath/also//here/*"]

我发现的快速而肮脏的解决方案是首先删除所有带引号的字符串,然后仅测试xpath字符(实际上是/@)。

const isXpath = str=>
/[/@]/.test(                     // find / or @ in
str.split(/['"`]/)            // cut on any quote
.filter( (s,i)=> !(i%2) ) // remove 1 on 2
.join('')                 // string without quotes
)

isXpath( 'nav [itemtype="https://schema.org/BreadcrumbList"] [itemtype="https://schema.org/ListItem"]' )
//> false 
// Actually search chars on "nav [itemtype=] [itemtype=]"

/!\ 请注意,这并不完美,有些情况会令人困惑,例如本讨论中给出的示例*div将回退到 CSS(isXpath = false)。你可以完美地引用字符串(转义的引号呢?),然后xpath字符...

最新更新