выражение xpath для числового сравнения

#xpath #greasemonkey

#xpath #greasemonkey

Вопрос:

Я пишу скрипт Greasemonkey, поэтому не могу изменить исходный XHTML.

Учитывая следующий фрагмент XHTML:

 <td>
    <span class="entry">Gender, Age:</span> Female, 42<br>
    <span class="entry">Country, Town:</span> United Kingdom, London 
    <span class="small09"></span>
</td>
  

возможно ли написать выражение, которое можно вычислить с помощью document.evaluate, что позволит мне выбрать все записи, возраст которых превышает, скажем, 40? Я хочу что-то вроде следующего:

 var matches = document.evaluate("//table[tbody/tr[2]/td[1][number(SOMEHOW 
  MATCH THE AGE PART) > 40]]", 
  document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, 
  null);
  

Спасибо

Комментарии:

1. Хороший вопрос, 1. Смотрите мой ответ для полного и очень короткого однострочного решения XPath-expression.

Ответ №1:

Использовать:

 //table[tbody/tr[2]/td[1]
  [number(
    substring-after(normalize-space(span[1]/following-sibling::text()[1]),
                   ',')
          ) 
   > 
     40
    ] 
       ]
  

Комментарии:

1. 1 Правильный ответ XPath. Было бы сложно сделать что-то более общее в XPath 1.0

2. Вы уверены, что это работает в Firefox (Greasemonkey)? Я получаю: Exception... "The expression is not a legal expression." code: "51" nsresult: "0x805b0033 (NS_ERROR_DOM_INVALID_EXPRESSION_ERR)" .

3. @Brock-Adams: Хорошая уловка — спасибо. Я исправил эту проблему (отсутствовало одно окончание ] .

4. Не получил предупреждение о вашем комментарии; Я предполагаю, что «Brock-Adams» не соответствует «Brock Adams». В любом случае, решение теперь работает и научило меня еще нескольким XPath. 1.

5. @Brock Adams: Рад, что мой ответ был полезен.

Ответ №2:

Вы не можете использовать условные обозначения для текстового содержимого, но вы можете фильтровать результаты с помощью JavaScript.

Должно сработать что-то вроде этого:

 var targetCells     = document.evaluate (
                        "//table/tbody/tr[2]/td[1]",
                        document,
                        null,
                        XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
                        null
                    );

for (var J = targetCells.snapshotLength - 1;  J >= 0;  --J)
{
    var thisCell    = targetCells.snapshotItem (J);

    //--- Get the age.  Key off (fe)male, {age in decimal years}<br> in the text of the table cell
    var ageTxt      = thisCell.textContent.match (/male[, ] (d )/i);

    if (ageTxt  amp;amp;  ageTxt.length > 1)
    {
        var age     = parseInt (ageTxt[1]);
        if (age > 40)
        {
            //-----------------------
            //--- DO YOUR STUFF HERE.
            //-----------------------
        }
    }
}
  

Ответ №3:

Если вы задаете возраст в качестве атрибута, вы можете получить доступ к этому значению.

Что-то вроде

 <Person Gender="F" Age="42" />
  

Комментарии:

1. Я пишу скрипт greasemonkey и не могу изменить исходный HTML.