упругий поиск элементов через xpath? - PullRequest
1 голос
/ 06 января 2011

из моего предыдущего вопроса,

как ведет себя этот xpath?

Я обнаружил, что

html//p//table//tr//td/a

может справиться с любыми неожиданными элементамикоторые отображаются между указанным выше xpath.

Например, описанный выше xpath может обрабатывать:

html/p/div/table/tr/td/a
html/p/table/tr/td/b/div/a

Однако как я могу сформулировать xpath, который будет полностью устойчив к отсутствующим / неожиданным элементам?

Например, упомянутый в начале xpath не может обрабатывать следующее:

/html/table/tr/td/a (p is missing)
/html/div/span/table/tr/td/a (p is missing and position replaced with `div/span/`)

Существует ли синтаксис xpath для решения приведенного выше случая?Если нет, то какой будет альтернативный подход?

Моя интуиция говорит мне, что это невозможно с одним xpath, поэтому я использую следующий алгоритм с использованием псевдокода.

По сути, это будетразделите данный xpath и найдите ближайшего потомка для каждого предка.Если ожидаемый дочерний элемент не существует или является каким-либо другим элементом, он перебирает всех дочерних элементов текущего предка и пытается найти ожидаемого дочернего элемента.

function searchElement(){
elements[] =  "/html/p/table/tr/td/a".split("/");
thisElement = "";

for (element in elements) {
if (firstItem){ 
  thisElement = findElementByXpath(element);
}else{
try{
thisElement.findElementByXpath(element); //look for this element inside previous element (from previous iteration);
}catch(NotFoundException e){ //if element is not found, search all elements inside previous element, and look for it.

foundElement = false;
discoveredElement = thisElement.findElementByXpath("*");
while(foundElement != true){

  if (discoveredElement.findEleemntByXpath(element) != null){
    //successful, element found, overwrite.
     thisElement = thisElement.findElementByXpath("*").findEleemntByXpath(element);
     foundElement = true;
  }else{
    //not successful, keep digging.
    discoveredElement = discoveredElement.findElementByXpath("*");
  }

}
}
}
}

return thisElement;
}

Это оптимальный подход?Меня беспокоит, что поиск "*" и копание в каждом элементе довольно неэффективны.

Я не знаю, что пометить этим вопросом, кроме "xpath" ... не стесняйтесь редактировать.

Спасибо.

Ответы [ 2 ]

1 голос
/ 06 января 2011

Если я правильно вас понимаю, вы хотите выбрать a элементов с конкретными заказанными необязательными предками.

Тогда твое выражение: /html//p//table//tr//td/a

Должно быть:

//a[(self::*|parent::td)[1]
       [(self::*|ancestor::tr)[1]
           [(self::*|ancestor::table)[1]
               [(self::*|ancestor::p)[1]
                        [ancestor::html[not(parent::*)]]
               ]
           ]
       ]
   ]

Но это так же, как:

/html//a |
/html//td/a |
/html//tr//a |
/html//tr//td/a |
/html//table//a |
/html//table//td/a |
/html//table//tr//a |
/html//table//tr//td/a |
/html//p//a |
/html//p//td/a |
/html//p//tr//a |
/html//p//tr//td/a |
/html//p//table//a |
/html//p//table//td/a |
/html//p//table//tr//a |
/html//p//table//tr//td/a |

и /html//a настолько общие, что они могут выбрать любой a

1 голос
/ 06 января 2011

Это возможно, но действительно плохая идея.

Конструкция // означает «пропустить любое количество элементов».Таким образом, вы можете использовать путь //td, чтобы найти элемент "td" в любом месте DOM.

Это означает, что вы выберете элемент в /html/body/im/not/what/you/want/td

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...