Xpath для выбора следующего брата У меня есть фрагмент HTML: <dt>name</dt> <dd>value</dd> <dt>name2</dt> <dd>value2</dd> Я хочу найти все места, где структура неверна, т.е. тег dd после тега dt. Я пробовал это: //dt/following-sibling::dt но это не работает. Любые предложения? Ответ 1 ИЗМЕНИТЬ, как отмечено @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. Ответ 2 Я не уверен, что понимаю вас, но есть мое решение. Этот XPath соответствует ALL <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 ) ] они делают то же самое
Ответ 1 ИЗМЕНИТЬ, как отмечено @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.
Ответ 2 Я не уверен, что понимаю вас, но есть мое решение. Этот XPath соответствует ALL <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 ) ] они делают то же самое