XPath для интервалов внутри элементов списка после абзаца - PullRequest
0 голосов
/ 04 сентября 2018

У меня есть следующий документ:

<html>
<head>
<title>Page</title>
</head>

<body>

<div>
    <div>
        <div>
        </div>
        <div class="this one">
            <p><span><strong>Ignore</strong></span></p>
                <p>Text</p>
            <p><span><strong>Header 1</strong></span></p>
                <ul><li><span style="color: #000;">List Value 1</span></li></ul>
            <p><span><strong>Header 2</strong></span></p>
                <ul><li><span style="color: #000;">List Value 2</span></li></ul>
            <p><span><strong>Ignore</strong></span></p>
                <ul><li><span style="color: #000;">List Value 3</span></li></ul>
            <p><span><strong>Header 3</strong></span></p>
                <ul>
                    <li><span style="color: #000;">List Value A</span></li>
                    <li><span style="color: #000;">List Value B</span></li>
                    <li><span style="color: #000;">List Value C</span></li>
                </ul>
            <p><span><strong>Ignore</strong></span></p>
                <p>Text</p>
        </div>
    </div>
</div>

</body>
</html>

Я пытаюсь получить все значения списка в Header 3; однако XPath не находит соответствия после <p>

Это работает:

//div[@class='this one']/p/span/strong[text() = 'Header 3']

Это не:

//div[@class='this one']/p/span/strong[text() = 'Header 3']/following-sibling::ul[1]/li/span

Ответы [ 2 ]

0 голосов
/ 04 сентября 2018

Проблема в том, что ваше выражение XPath поднимается до <strong>, у которого нет родных элементов (это единственный дочерний элемент его родительского элемента <span>). Элемент со следующим братом <ul> находится на <p> дальше вверх.

В общем, у вас есть два варианта:

  • Спускайтесь вниз, затем обратно:

    //div[@class='this one']/p/span/strong[text() = 'Header 3']/../../following-sibling::ul/li/span
    

    .. является сокращением для parent::node().

  • Используйте прогнозное выражение:

    //div[@class='this one']/p[span/strong[text() = 'Header 3']]/following-sibling::ul/li/span
    

    Все в [ ] - это условие фильтра, которое не перемещает текущую позицию в дереве документа. Вы можете поместить туда произвольные выражения XPath. Здесь мы используем его, чтобы найти p, который содержит span, который содержит strong с заданным текстом.

Демо-версия:

function xpath(expr) {
  var found = document.evaluate(expr, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  var results = [];
  for (var i = 0; i < found.snapshotLength; i++) {
    results.push(found.snapshotItem(i));
  }
  return results;
}

console.log(xpath("//div[@class='this one']/p/span/strong[text() = 'Header 3']/../../following-sibling::ul/li/span"));

console.log(xpath("//div[@class='this one']/p[span/strong[text() = 'Header 3']]/following-sibling::ul/li/span"));
<div>
    <div>
        <div>
        </div>
        <div class="this one">
            <p><span><strong>Ignore</strong></span></p>
                <p>Text</p>
            <p><span><strong>Header 1</strong></span></p>
                <ul><li><span style="color: #000;">List Value 1</span></li></ul>
            <p><span><strong>Header 2</strong></span></p>
                <ul><li><span style="color: #000;">List Value 2</span></li></ul>
            <p><span><strong>Ignore</strong></span></p>
                <ul><li><span style="color: #000;">List Value 3</span></li></ul>
            <p><span><strong>Header 3</strong></span></p>
                <ul>
                    <li><span style="color: #000;">List Value A</span></li>
                    <li><span style="color: #000;">List Value B</span></li>
                    <li><span style="color: #000;">List Value C</span></li>
                </ul>
            <p><span><strong>Ignore</strong></span></p>
                <p>Text</p>
        </div>
    </div>
</div>
0 голосов
/ 04 сентября 2018

Проблема в том, что strong не имеет ul следующих братьев и сестер.

Изменение

//div[@class='this one']/p/span/strong[text() = 'Header 3']/following-sibling::ul[1]/li/span

до

//div[@class='this one']/p[span='Header 3']/following-sibling::ul[1]/li/span

потому что p имеет ul следующего брата. Тогда вы выберете

<span style="color: #000;">List Value A</span>
<span style="color: #000;">List Value B</span>
<span style="color: #000;">List Value C</span>

по запросу.

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