Xpath для выбора следующего родного брата - PullRequest
20 голосов
/ 19 января 2010

У меня есть кусок HTML, как это:

<dt>name</dt>
<dd>value</dd>
<dt>name2</dt>
<dd>value2</dd>

Я хочу найти все места, где структура неверна, то есть после тега dt нет тега dd.

Я пробовал это:

//dt/following-sibling::dt

но это не работает. Есть предложения?

Ответы [ 2 ]

16 голосов
/ 19 января 2010

Я не уверен, что понимаю вас, но есть мое решение. Этот XPath соответствует ВСЕМ <dt>, за которыми не следует <dd> напрямую. Итак, есть тестовая структура

<xml>
  <dt>name</dt> <!-- match -->

  <dt>name2</dt>
  <dd>value2</dd>

  <dt>name</dt>
  <dd>value</dd>

  <dt>name2</dt>  <!-- match -->
</xml>

Есть XPath

//dt[ name( following-sibling::*[1] ) != 'dd' ]

или

//dt[  not( following-sibling::*[1]/self::dd ) ]

они делают то же самое

16 голосов
/ 19 января 2010

РЕДАКТИРОВАТЬ , как отмечает @Gaim, моей исходной версии не удалось захватить терминал dt

string xml = @"
    <root>
    <dt>name</dt>
    <dd>value</dd>
    <dt>name2</dt>
    <dt>name3</dt>
    <dd>value3</dd>
    <dt>name4</dt>
    <dt>name5</dt>
    <dd>value5</dd>
    <dt>name6</dt>
    </root>
    ";

XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);

XmlNodeList nodes = 
    doc.SelectNodes("//dt[not(following-sibling::*[1][self::dd])]");

foreach (XmlNode node in nodes)
{
    Console.WriteLine(node.OuterXml);
}

Console.ReadLine();

Вывод - это те dt узлы, у которых нет dd, следующих непосредственно за ними:

<dt>name2</dt>
<dt>name4</dt>
<dt>name6</dt>

То, что мы здесь делаем, говорит:

//dt

Все dt узлы, где угодно ....

[not(following-sibling::*[1]

.... такой, что не тот случай, когда их первый следующий брат (как его там называют) ....

[self::dd]]

... называется dd.

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