Запросы XPath в IE используют индексы, начинающиеся с нуля, но спецификация W3C основана на единицах. Как мне справиться с разницей? - PullRequest
6 голосов
/ 22 декабря 2011

Проблема

Я конвертирую относительно большой кусок Javascript, который в настоящее время работает только в Internet Explorer, чтобы он работал и в других браузерах. Поскольку код широко использует XPath, мы сделали небольшую функцию совместимости, чтобы упростить процесс

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

Это в основном работает нормально, но мы только что натолкнулись на ограничение, что позиции в IE основаны на нуле, но в модели W3C, используемой другими браузерами, они основаны на одном . Это означает, что для получения первого элемента нам нужно сделать //books[0] в IE и //books[1] в других браузерах.

Мое предлагаемое решение

Первой мыслью было использование регулярного выражения для добавления одного ко всем индексам, которые появляются в запросах, если мы используем версию document.evaluate:

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, чтобы облегчить процесс конвертации.


В итоге

Мы решили переписать код для использования правильного XPath в IE, установив язык выбора

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

Ответы [ 2 ]

8 голосов
/ 22 декабря 2011

мы только что натолкнулись на ограничение, что позиции в IE основаны на нуле, но в модели W3C, используемой другими браузерами, они основаны на одном.Это означает, что для получения первого элемента нам нужно сделать //books[0] в IE и //books[1] в других браузерах.

Перед выполнением любого выбора XPath укажите :

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

MSXML3 использует диалект XSLT / XPath, который использовался до того, как XSLT и XPath стали Рекомендациями W3C .По умолчанию используется «XSLPattern», и это то, что вы видите как поведение.

Подробнее об этом можно прочитать здесь:

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

1 голос
/ 22 декабря 2011

Почему бы не изменить исходные выражения, чтобы это:

var expr = "books[1]";

... становится:

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

... где index определяется как (псевдокод):

function index(i) {
    return isIE ? (i - 1) : i;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...