Javascript IE中的XPath查询使用基于零的索引,但W3C规范是基于零的索引。我应该如何处理差异? 问题
我正在转换一个相对较大的Javascript,它目前只在internetexplorer上工作,以便使它也能在其他浏览器上工作。由于代码广泛使用XPath,我们制作了一个小的兼容性函数,使事情变得更简单Javascript IE中的XPath查询使用基于零的索引,但W3C规范是基于零的索引。我应该如何处理差异? 问题,javascript,internet-explorer,xpath,cross-browser,Javascript,Internet Explorer,Xpath,Cross Browser,我正在转换一个相对较大的Javascript,它目前只在internetexplorer上工作,以便使它也能在其他浏览器上工作。由于代码广泛使用XPath,我们制作了一个小的兼容性函数,使事情变得更简单 function selectNodes(xmlDoc, xpath){ if('selectNodes' in xmlDoc){ //use IE logic }else{ //use W3C's document.evaluate }
function selectNodes(xmlDoc, xpath){
if('selectNodes' in xmlDoc){
//use IE logic
}else{
//use W3C's document.evaluate
}
}
这基本上可以正常工作,但我们刚刚遇到了一个限制,即IE中的位置是基于零的,但在其他浏览器使用的W3C模型中,它们是基于一个的。这意味着要获取第一个元素,我们需要在IE中执行//books[0]
,在其他浏览器中执行//books[1]
我提出的解决办法
第一个想法是使用正则表达式将一个添加到查询中出现的所有索引中(如果使用文档)。评估版本:
function addOne(n){ return 1 + parseInt(nStr, 10); }
xpath = xpath.replace(
/\[\s*(\d+)\s*\]/g,
function(_, nStr){ return '[' + addOne(nStr) + ']'; }
);
我的问题
这种基于正则表达式的解决方案合理安全吗?
- 有没有什么地方它可以转换一些它不应该转换的东西
- 有没有什么地方它不会转换它应该转换的东西
//books[position()=1]
中的索引,但由于IE似乎不支持position()
,并且我们的代码没有使用,因此我认为这种特殊情况不会有问题
考虑
- 我下载来看看他们是否有办法解决这个问题,但在看了源代码之后,他们显然没有
- 我想在W3C版本中添加一个,而不是在IE版本中减去一个,以简化转换工作
最后 我们决定通过设置选择语言来重写代码,以便在IE中使用适当的XPath
xmlDoc.setProperty("SelectionLanguage", "XPath");
为什么不修改原始表达式,以便:
var expr = "books[1]";
…变成:
var expr = "books[" + index(1) + "]";
…其中,索引
定义为(伪代码):
我们刚刚遇到了IE中的位置为零的限制
但是在其他浏览器使用的W3C模型中,它们是基于一个的。
这意味着要获取第一个元素,我们需要在
IE和其他浏览器中的//books[1]
在进行任何XPath选择之前,请指定:
xmlDoc.setProperty("SelectionLanguage", "XPath");
MSXML3使用XSLT/XPath方言,在XSLT和XPath成为W3C推荐标准之前就已经使用了。默认值是“XSLPattern”,这就是您所看到的行为
请在此处阅读有关此主题的更多信息:
但我如何知道在哪里调用此函数?如果我所做的只是手工替换
[n]
模式,那么我更喜欢不引人注目的正则表达式。它在构造表达式时会被调用,如上面的示例所示。问题是我必须转换大量最初由其他人生成的表达式。我如何知道我必须在哪里添加一个索引
调用,以及在哪里不做任何事情?关于如何从XSLPattern转换为XPath,您有什么建议或参考资料吗?除了错误的索引之外,还有什么我应该担心的吗?@missingno:如果您已经使用了XSLPattern,那么尝试将其转换为XPath是不明智的——我最好的建议是将这段遗留代码重写为符合XSLT 1.0/XPath 1.0的代码。这很有意义。但是,是否有一个兼容的索引版本(或者至少获取第一个元素,因为这是最常见的情况)或者我必须将查询拆分为多个部分并手动进行索引?@missingno:我仍然不明白:您是否有使用旧“XSLPattern”方言的代码?如果没有,那么就没有任何问题——只需使用xmlDoc.setProperty(“SelectionLanguage”、“XPath”)在调用转换之前执行代码>。这将COM对象设置为使用“XPath”选择语言——这是所有其他浏览器都使用的标准XPath 1.0。如上所述设置此属性后,索引从1开始。是的,它使用的是旧方言:(.我现在想知道,如果我需要将//books[0]/book
之类的内容重写为doc.selectNodes('//books')[0]。selectNodes('/book')
xmlDoc.setProperty("SelectionLanguage", "XPath");