Выберите узел XML через XPath на произвольной глубине - PullRequest
4 голосов
/ 09 июля 2011

Имея XML-документ, я хочу получить первый узел с определенным именем, независимо от того, в какой глубине вложенности он содержится.

Я несколько раз безуспешно пытался:

var node1 = doc.SelectSingleNode(@"//Shortcut");
var node2 = doc.SelectSingleNode(@"/*/Shortcut");
var node3 = doc.SelectSingleNode(@"//*/Shortcut");
var node4 = doc.SelectSingleNode(@"*/Shortcut");
...

Каждый вызов приводит к узлу NULL.

Я думаю, что это должен быть какой-то тривиальный синтаксис XPath.Можете ли вы мне помочь?

(Если это имеет значение: XML-документ является входным файлом для проекта WiX , поэтому могут возникнуть некоторые проблемы с пространством имен?!?).

Редактировать

Я также попробовал следующее:

var nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace(string.Empty, @"http://schemas.microsoft.com/wix/2006/wi");
nsm.AddNamespace(@"ns", @"http://schemas.microsoft.com/wix/2006/wi");

вместе с:

var node1 = doc.SelectSingleNode(@"//Shortcut", nsm);
var node2 = doc.SelectSingleNode(@"/*/Shortcut", nsm);
var node3 = doc.SelectSingleNode(@"//*/Shortcut", nsm);
var node4 = doc.SelectSingleNode(@"*/Shortcut", nsm);
...

Приводит к тем же результатам.

Редактировать 2 - Решение

Я нашел решение:

var nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace(string.Empty, @"http://schemas.microsoft.com/wix/2006/wi");
nsm.AddNamespace(@"ns", @"http://schemas.microsoft.com/wix/2006/wi");

, а затем

var node1 = doc.SelectSingleNode(@"//ns:Shortcut", nsm);

Это успешно.

Ответы [ 3 ]

2 голосов
/ 09 июля 2011

Я наконец нашел решение самостоятельно:

var nsm = new XmlNamespaceManager(doc.NameTable);
nsm.AddNamespace(string.Empty, @"http://schemas.microsoft.com/wix/2006/wi");
nsm.AddNamespace(@"ns", @"http://schemas.microsoft.com/wix/2006/wi");

, а затем

var node1 = doc.SelectSingleNode(@"//ns:Shortcut", nsm);

Это удалось.

2 голосов
/ 09 июля 2011

Выражение XPath, которое выбирает именно нужный узел (и ничего кроме этого): :

(//x:Shortcut)[1]

Итак, используя:

doc.SelectNodes("(//x:Shortcut)[1]", someNamespaceManager)

, где

префикс "x" связан с пространством имен "http://schemas.microsoft.com/wix/2006/wi"

в someNamespaceManager

Это имеет преимущество перед предлагаемым решением (для использования SelectSingleNode()), поскольку его можно легко настроить для выбора N-го желаемого узла в документе XML .

Например:

   (//x:Shortcut)[3]

выбирает третий (в порядке документа) элемент x:Shortcut и

   (//x:Shortcut)[last()]

выбирает последний (в порядке документа) элемент x:Shortcut в документе XML.

2 голосов
/ 09 июля 2011

Почему бы не использовать XDocument ?

XDocument doc = XDocument.Load("test.xml");
doc.Descendants("Shortcut").First();

IMO XDocument быстрее и удобочитаемее, чем XPath.

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