我认为默认浏览器 XPath 实现不支持 EXSLT。EXSLT 页面上提到的 javascript 支持可能是关于如何使用 in-browser.javascript 提供自己的 exslt 函数实现。这是我能很快找到的一个例子。
例如,在 Firefox 中,您可以将Saxon-B 作为扩展来运行 XSLT2.0,并且Saxon-B 具有对 exslt 的内置支持(与 Saxon-HE 不同),尽管使用 XSLT/XPath 可能会更好2.0 功能。例如,这是正则表达式语法。尽管如此,依靠 Mozilla Saxon-B 扩展程序并不能帮助您使用 Chrome 或其他浏览器。
话虽如此,我认为您找不到在 XPath 中使用 EXSLT 扩展的跨浏览器解决方案。DOM Level 3 XPath的一致性部分要求支持 XPath 1.0,但没有提到 EXSLT。据说INVALID_EXPRESSION_ERR
被抛出:
if the expression has a syntax error or otherwise is not a legal expression according to the rules of the specific XPathEvaluator or contains specialized extension functions or variables not supported by this implementation.
最后,这是一个开放的 bugzilla 票证,供 Firefox 为他们的 DOM Level 3 XPath 实现开放 EXSLT 支持。自 2007 年以来,它似乎一直处于 NEW 状态。票据上写着:
Currently Mozilla gives an exception "The expression is not a legal expression." even if a namespace resolver correctly resolving the EXSLT prefixes to the corresponding URLs is passed in
. 这是测试用例。
--
如果你不介意我问,你到底想用正则表达式做什么?也许我们可以帮助您摆脱标准 XPath 字符串函数的组合?
--
更新您可以通过 XSLT 构建一个 XPath 运行器(就像您在更新问题时提出的那样),但它不会返回源文档中的节点,它会返回看起来完全相同的新节点。XSLT 生成一个新的结果树文档,我认为没有办法让它返回对原始节点的引用。
据我所知,Mozilla(和 Chrome)都支持 XSLT,不仅支持从外部源加载的 XML 文档,还支持正在显示的文档中的 DOM 元素。该XSLTProcessor
文档提到了如何tranformToFragment()
,例如,will only produce HTML DOM objects if the owner document is itself an HTMLDocument, or if the output method of the stylesheet is HTML
。
这是一个简单的 XPath Runner,我构建了它来测试您的 ide:
1) 首先,您需要一个 XSLT 模板才能使用。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:regexp="http://exslt.org/regular-expressions"
extension-element-prefixes="regexp">
<xsl:template match="/">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>
我开始使用 APi 在 JavaScript 中构建它,document.implementation.createDocument
但认为加载它会更容易。FF 仍然支持document.load
,而 Chrome 只允许您使用 XHR 加载内容。--allow-file-access-from-files
如果您想使用 XHR 从本地磁盘加载文件,则需要启动 Chrome 。
2) 一旦我们加载了模板,我们需要修改指令select
属性的值来运行我们需要的 XPath:xsl:copy-of
function runXPath(xpath) {
var processor = new XSLTProcessor();
var xsltns = 'http://www.w3.org/1999/XSL/Transform';
var xmlhttp = new window.XMLHttpRequest();
xmlhttp.open("GET", "xpathrunner.xslt", false);
xmlhttp.send(null);
var transform = xmlhttp.responseXML.documentElement;
var copyof = transform.getElementsByTagNameNS(xsltns, 'copy-of')[0];
copyof.setAttribute('select', xpath);
processor.importStylesheet(transform);
var body = document.getElementById('body'); // I gave my <body> an id attribute
return processor.transformToFragment(body, document);
}
您现在可以使用以下内容运行它:
var nodes = runXPath('//div[@id]');
console.log(nodes.hasChildNodes());
if (nodes.firstChild) {
console.log(nodes.firstChild.localName);
}
它非常适合像这样的“常规”XPath //div[@id]
(并且无法找到//div[@not-there]
),但我就是无法让它运行regexp:test
扩展功能。有了//div[regexp:test(string(@id), "a")]
它不会出错,只返回空集。
Mozilla 文档建议他们的 XSLT 处理器支持 EXSLT。我想他们无论如何都在幕后使用 libxml/libxslt。也就是说,我也无法让它在 Mozilla 中工作。
希望能帮助到你。
你有机会摆脱jQuery regexp吗?不太可能对您的 XPath 构建器实用程序有帮助,但仍然是在 HTML 节点上运行正则表达式的一种方式。