我想在使用exslt扩展的Web应用程序中使用javascript XPath,但我无法弄清楚如何执行此操作。
假装我有一个带有一些div的html doc。我想运行这个:
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);
只有这会在evaluate中导致无效的XPath表达式异常。我正在使用chrome。
还有什么我需要做才能使这些东西有效吗?我在exslt.org上看到有javascript的实现,但我如何确保它们可用?我是否需要将我的javascript插入dom中的命名空间脚本元素或疯狂的东西?
更新
如果不能直接使用浏览器dom + javascript和xpath,是否可以在浏览器中使用exslt扩展编写XSLT来模拟document.evaluate(返回与xpath匹配的元素列表)?
答案 0 :(得分: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.0和Saxon-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.
最后,这是Firefox的open bugzilla ticket,为他们的DOM Level 3 XPath实现开放EXSLT支持。它自2007年以来似乎一直处于新状态。机票说:
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,我构建了测试你的ides:
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)一旦我们加载了模板,我们需要修改select
指令的xsl:copy-of
属性的值来运行我们需要的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);
}
它非常适合“常规”XPath,例如//div[@id]
(并且无法找到//div[@not-there]
),但我无法让它运行regexp:test
扩展功能即可。使用//div[regexp:test(string(@id), "a")]
它不会出错,只返回空集。
Mozilla文档建议their XSLT processor support EXSLT。我想他们无论如何都会在幕后使用libxml / libxslt。也就是说,我无法让它在Mozilla中工作。
希望它有所帮助。
你有机会逃脱jQuery regexp吗?不太可能对您的XPath构建器实用程序有帮助,但仍然是在HTML节点上运行regexp的方法。