【问题标题】:Using exslt extentions be used in javascript xpaths在 javascript xpaths 中使用 xslt 扩展
【发布时间】:2012-05-17 11:50:53
【问题描述】:

我想在使用 exslt 扩展的 Web 应用程序中使用 javascript XPaths,但我不知道该怎么做。

假设我有一个包含一些 div 的 html 文档。我想运行这个:

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 匹配的元素列表)?

【问题讨论】:

  • 您是否考虑过使用 SaxonCE——它支持在浏览器中执行 XSLT 2.0(并在包括 Chrome 在内的所有五种主要浏览器上成功运行)?
  • 如果他们公开了一个与他们的 XSLT20Processor 等效的 javascript XPath20Evaluator,那就太棒了。不幸的是,他们还没有提供这个选项。不过,谢谢你的提示。很高兴知道它就在那里。
  • 您无需等待“他们”。只需获得您的 SaxonCE 许可证并使用它。

标签: javascript dom xpath webkit exslt


【解决方案1】:

我认为默认浏览器 XPath 实现不支持 EXSLT。 EXSLT 页面上提到的 javascript 支持可能是关于如何使用 in-browser.javascript 提供自己的 exslt 函数实现。这是one example I was able to find very quickly

例如,在 Firefox 中,您可以拥有 Saxon-B as an extension to run XSLT2.0Saxon-B has built-in support for exslt (unlike Saxon-HE), though you will likely be better off just using XSLT/XPath 2.0 features。例如,这是regular expression syntax。尽管如此,依靠 Mozilla Saxon-B 扩展程序并不能帮助您使用 Chrome 或其他浏览器。

话虽如此,我认为您找不到在 XPath 中使用 EXSLT 扩展的跨浏览器解决方案。 DOM Level 3 XPath 的conformance section 要求支持 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.

最后,这里有一个open bugzilla ticket 供 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。这是test case

--

如果您不介意我问,您究竟想使用正则表达式做什么?也许我们可以通过standard XPath string functions 的组合帮助您摆脱困境?

--

更新您可以通过 XSLT 构建一个 XPath 运行器(就像您在更新问题时提出的那样),但 它不会从源文档返回节点,它会返回看起来完全相同的新节点。 XSLT 生成一个新的结果树文档,我认为没有办法让它返回对原始节点的引用。

据我所知,Mozilla(和 Chrome)support XSLT 不仅适用于从外部源加载的 XML 文档,还适用于正在显示的文档中的 DOM 元素。 XSLTProcessor documentation 提到了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>

我开始使用 document.implementation.createDocument APi 在 JavaScript 中构建它,但我认为加载它会更容易。 FF 仍然支持document.load,而 Chrome 只允许您使用 XHR 加载内容。如果您想使用 XHR 从本地磁盘加载文件,您需要使用 --allow-file-access-from-files 启动 Chrome。

2) 一旦我们加载了模板,我们需要修改 xsl:copy-of 指令的 select 属性的值来运行我们需要的 XPath:

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);
}

它非常适合像 //div[@id] 这样的“常规”XPath(并且无法找到 //div[@not-there]但我就是无法让它运行 regexp:test 扩展功能。使用//div[regexp:test(string(@id), "a")] 它不会出错,只会返回空集。

Mozilla 文档建议their XSLT processor support EXSLT。我想他们无论如何都在幕后使用 libxml/libxslt。也就是说,我也无法让它在 Mozilla 中工作。

希望对您有所帮助。

你有没有机会摆脱jQuery regexp?不太可能对您的 XPath 构建器实用程序有帮助,但仍然是在 HTML 节点上运行正则表达式的一种方式。

【讨论】:

  • 那么前景黯淡。我也在看只支持chrome。目的不是创建一个特定的正则表达式过滤的 xpath,而是在 html/css/javascript 中创建一个 xpath 创建者,类似于 chrome 扩展 XPath Helper(请参阅chrome.google.com/webstore/detail/…)。
  • 也许可以在他们的 wiki / 邮件列表中询问。我搜索了 EXSLT 的 wiki 和问题,发现了这个:code.google.com/p/chromium/issues/…。他们必须在那里对 EXSLT 有一些支持,但我不确定它是否通过 DOM Level 3 XPath 公开。知道 Mozilla 如何在 DOM XPath 中没有它,即使他们的 XSLT 中似乎也有它,我认为 Chrome 也没有。
  • @SynapticUnderrun 我发布了一个更新,探索基于 XSLT 的 XPath 运行器理念。它可以工作,但运行 regexp: 扩展函数时运气不佳。
猜你喜欢
  • 2012-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-29
  • 1970-01-01
  • 1970-01-01
  • 2015-10-03
  • 1970-01-01
相关资源
最近更新 更多