3

我想在使用 exslt 扩展的网络应用程序中使用 javascript XPaths,但我不知道如何做到这一点。

假装我有一个 html 文档,里面有一些 div。我想运行这个:

namespaces={'regexp':'http://exslt.org/regular-expressions'};
result = document.evaluate( 
             "//div[regexp:test(.,'$')]", 
             document, 
             function(ns){ 
                 return namespaces.hasOwnProperty(ns) ? namespaces[ns] : null;
             }, 
             XPathResult.ANY_TYPE, 
             null);

只有这样会在评估中导致无效的 XPath 表达式异常。我正在使用铬。

我还需要做些什么来使这些东西正常工作吗?我在 exslt.org 上看到有 javascript 的实现,但我如何确保它们可用?我是否需要将我的 javascript 插入到 dom 中的命名空间脚本元素中或一些疯狂的东西中?

更新

如果直接使用浏览器 dom + javascript 和 xpath 无法做到这一点,是否可以在浏览器中使用 exslt 扩展编写 XSLT 来模拟 document.evaluate(返回与 xpath 匹配的元素列表)?

4

1 回答 1

1

我认为默认浏览器 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 节点上运行正则表达式的一种方式。

于 2012-05-14T18:00:21.967 回答