最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - XPath queries in IE use zero-based indexes but the W3C spec is one-based. How should I handle the difference? - Sta

programmeradmin1浏览0评论

The Problem

I am converting a relatively large piece of Javascript that currently only works on Internet Explorer in order to make it work on the other browsers as well. Since the code uses XPath extensively we made a little patibility function to make things easier

function selectNodes(xmlDoc, xpath){
    if('selectNodes' in xmlDoc){
        //use IE logic
    }else{
        //use W3C's document.evaluate
    }
}

This is mostly working fine but we just came across the limitation that positions in IE are zero-based but in the W3C model used by the other browsers they are one-based. This means that to get the first element we need to do //books[0] in IE and //books[1] in the other browsers.

My proposed solution

The first thought was using a regex to add one to all indexes that appear in the queries if we are using the document.evaluate version:

function addOne(n){ return 1 + parseInt(nStr, 10); }

xpath = xpath.replace(
    /\[\s*(\d+)\s*\]/g,
    function(_, nStr){ return '[' + addOne(nStr) + ']'; }
);

My question

Is this regex based solution reasonably safe?

  • Are there any places it will convert something it should not?
  • Are there any places where it will not convert something it should?

For example, it would fail to replace the index in //books[position()=1] but since IE doesn't appear to support position() and our code is not using that I think this particular case would not be a problem.


Considerations

  • I downloaded Sarissa to see if they have a way to solve this but after looking at the source code apparently they don't?

  • I want to add one to the W3C version instead of subtracting one in the IE version to ease my conversion effort.


In the end

We decided to rewrite the code to use proper XPath in IE too by setting the selection language

xmlDoc.setProperty("SelectionLanguage", "XPath");

The Problem

I am converting a relatively large piece of Javascript that currently only works on Internet Explorer in order to make it work on the other browsers as well. Since the code uses XPath extensively we made a little patibility function to make things easier

function selectNodes(xmlDoc, xpath){
    if('selectNodes' in xmlDoc){
        //use IE logic
    }else{
        //use W3C's document.evaluate
    }
}

This is mostly working fine but we just came across the limitation that positions in IE are zero-based but in the W3C model used by the other browsers they are one-based. This means that to get the first element we need to do //books[0] in IE and //books[1] in the other browsers.

My proposed solution

The first thought was using a regex to add one to all indexes that appear in the queries if we are using the document.evaluate version:

function addOne(n){ return 1 + parseInt(nStr, 10); }

xpath = xpath.replace(
    /\[\s*(\d+)\s*\]/g,
    function(_, nStr){ return '[' + addOne(nStr) + ']'; }
);

My question

Is this regex based solution reasonably safe?

  • Are there any places it will convert something it should not?
  • Are there any places where it will not convert something it should?

For example, it would fail to replace the index in //books[position()=1] but since IE doesn't appear to support position() and our code is not using that I think this particular case would not be a problem.


Considerations

  • I downloaded Sarissa to see if they have a way to solve this but after looking at the source code apparently they don't?

  • I want to add one to the W3C version instead of subtracting one in the IE version to ease my conversion effort.


In the end

We decided to rewrite the code to use proper XPath in IE too by setting the selection language

xmlDoc.setProperty("SelectionLanguage", "XPath");
Share Improve this question edited Dec 24, 2011 at 1:59 hugomg asked Dec 22, 2011 at 14:54 hugomghugomg 70.1k29 gold badges166 silver badges255 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 8

we just came across the limitation that positions in IE are zero-based but in the W3C model used by the other browsers they are one-based. This means that to get the first element we need to do //books[0] in IE and //books[1] in the other browsers.

Before doing any XPath selection, specify:

xmlDoc.setProperty("SelectionLanguage", "XPath");

MSXML3 uses a dialect of XSLT/XPath that was in use before XSLT and XPath became W3C Remendations. The default is "XSLPattern" and this is what you see as behavior.

Read more on this topic here:

http://msdn.microsoft./en-us/library/windows/desktop/ms754679(v=vs.85).aspx

Why not modify the original expressions, so that this:

var expr = "books[1]";

...bees:

var expr = "books[" + index(1)  + "]";

...where index is defined as (pseudocode):

function index(i) {
    return isIE ? (i - 1) : i;
}

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论