似乎没有多少人通过 CSS 选择器搜索但希望将结果作为 XPath,但有一些选项可以实现。
首先,我使用 JQuery 加上一个附加功能来完成这项工作。这是因为 JQuery 有很好的选择并且很容易找到支持。您可以use JQuery in Node.js,因此您应该能够在该域(在服务器上)而不是在客户端(如我的简单示例中所示)中实现我的代码。如果这不是一个选项,您可以在下面查找我使用 Python 的其他潜在解决方案,或者在底部查找 C# starter。
对于 JQuery 方法,纯 JavaScript 函数返回 XPath 非常简单。在以下示例 (also on JSFiddle) 中,我使用 JQuery 选择器检索示例锚元素,获取剥离的 DOM 元素,并将其发送到我的 getXPath 函数:
<html>
<head>
<title>The jQuery Example</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
function getXPath( element )
{
var xpath = '';
for ( ; element && element.nodeType == 1; element = element.parentNode )
{
var id = $(element.parentNode).children(element.tagName).index(element) + 1;
id > 1 ? (id = '[' + id + ']') : (id = '');
xpath = '/' + element.tagName.toLowerCase() + id + xpath;
}
return xpath;
}
$(document).ready(function() {
$("#example").click(function() {
alert("Link Xpath: " + getXPath($("#example")[0]));
});
});
</script>
</head>
<body>
<p id="p1">This is an example paragraph.</p>
<p id="p2">This is an example paragraph with a <a id="example" href="#">link inside.</a></p>
</body>
</html>
如果您需要比我提供的复杂度更高的复杂性,有一个完整的库,用于更强大的 CSS 选择器到 XPath 转换,称为 css2xpath。
Python (lxml):
对于 Python,您需要使用 lxml 的 CSS 选择器类 (see link for full tutorial and docs) 来获取 xml 节点。
CSSSelector 类
lxml.cssselect 模块中最重要的类是 CSSSelector。
它提供与 XPath 类相同的接口,但接受 CSS
选择器表达式作为输入:
>>> from lxml.cssselect import CSSSelector
>>> sel = CSSSelector('div.content')
>>> sel #doctest: +ELLIPSIS <CSSSelector ... for 'div.content'>
>>> sel.css
'div.content'
选择器实际上编译为 XPath,你可以看到
通过检查对象来表达:
>>> sel.path
"descendant-or-self::div[@class and contains(concat(' ', normalize-space(@class), ' '), ' content ')]"
要使用选择器,只需使用文档或元素对象调用它:
>>> from lxml.etree import fromstring
>>> h = fromstring('''<div id="outer">
... <div id="inner" class="content body">
... text
... </div></div>''')
>>> [e.get('id') for e in sel(h)]
['inner']
使用 CSSSelector 相当于使用 cssselect 和
使用 XPath 类:
>>> from cssselect import GenericTranslator
>>> from lxml.etree import XPath
>>> sel = XPath(GenericTranslator().css_to_xpath('div.content'))
CSSSelector 带有一个翻译器参数让你选择哪个
翻译器使用。它可以是“xml”(默认)、“xhtml”、“html”或
翻译器对象。
如果您希望从 url 加载,您可以在构建 etree 时直接执行此操作:root = etree.fromstring(xml, base_url="http://where.it/is/from.xml")
C#
有一个名为 css2xpath-reloaded 的库,它只做 CSS 到 XPath 的转换。
String css = "div#test .note span:first-child";
String xpath = css2xpath.Transform(css);
// 'xpath' will contain:
// //div[@id='test']//*[contains(concat(' ',normalize-space(@class),' '),' note ')]*[1]/self::span
当然,使用 C# 实用程序类从 url 获取字符串非常容易,不需要讨论:
using(WebClient client = new WebClient()) {
string s = client.DownloadString(url);
}
至于 CSS 选择器的选择,你可以试试Fizzler,它非常强大。这是首页示例,尽管您可以做更多的事情:
// Load the document using HTMLAgilityPack as normal
var html = new HtmlDocument();
html.LoadHtml(@"
<html>
<head></head>
<body>
<div>
<p class='content'>Fizzler</p>
<p>CSS Selector Engine</p></div>
</body>
</html>");
// Fizzler for HtmlAgilityPack is implemented as the
// QuerySelectorAll extension method on HtmlNode
var document = html.DocumentNode;
// yields: [<p class="content">Fizzler</p>]
document.QuerySelectorAll(".content");
// yields: [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>]
document.QuerySelectorAll("p");
// yields empty sequence
document.QuerySelectorAll("body>p");
// yields [<p class="content">Fizzler</p>,<p>CSS Selector Engine</p>]
document.QuerySelectorAll("body p");
// yields [<p class="content">Fizzler</p>]
document.QuerySelectorAll("p:first-child");