Запрос XPath, похоже, не работает

#c# #xml #xpath

#c# #xml #xpath

Вопрос:

У меня возникли некоторые проблемы с выполнением запроса xpath на C #, с оговоркой, что я никогда раньше не использовал пространства имен, но в целом я понял идею. Сначала я создаю XML-документ как таковой и создаю диспетчер пространств имен.

 XmlDocument doc = new XmlDocument();
doc.Load(metaDataStream);
nsmgr = new XmlNamespaceManager(doc.NameTable);
rootNode = doc.ChildNodes[1];
nsmgr.AddNamespace(string.Empty, rootNode.Attributes["xmlns"].Value);
nsmgr.AddNamespace("xsi", rootNode.Attributes["xmlns:xsi"].Value);
nsmgr.AddNamespace("xsd", rootNode.Attributes["xmlns:xsd"].Value);
  

Затем позже в другом методе в классе я пытаюсь запросить xml как таковой….

 XmlNodeList selectedNodes = rootNode.SelectNodes("//somenode", nsmgr);
  

и в списке выбранных узлов всегда отображаются нулевые узлы, выбранные из приведенного ниже текста xml. Может кто-нибудь указать мне, где я ошибся? (в качестве примечания фактический XML не совсем такой, но по соображениям конфиденциальности мне не разрешено его раскрывать, поэтому я изо всех сил старался запутать данные, сохраняя те же свойства)

 <?xml version="1.0"?>
<ext xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" uuid="urn:uuid:03565202-d53b-4f26-83a2-4d94964ed4be" xmlns="http://www.something.com/ext/2010/10/01">
  <somenode someattribute="somevalue">
  </somenode>
</ext>
  

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

1. Похоже, что ваш XPath должен работать для предоставленного вами поддельного XML, что вызывает вопрос: «Вы УВЕРЕНЫ, что rootNode на самом деле является тем, что вы думаете?» Если вы еще этого не сделали, я бы попробовал распечатать для него XML непосредственно перед вызовом SelectNodes, чтобы убедиться, что это то, что вы думаете.

Ответ №1:

Я полагаю, что проблема заключается в том, что вы используете string.Empty в качестве псевдонима для пространства имен. Это работает:

 nsmgr.AddNamespace("def", rootNode.Attributes["xmlns"].Value);
...            
XmlNodeList selectedNodes = rootNode.SelectNodes("//def:somenode", nsmgr);
  

В принципе, пока вы даете ему псевдоним, он работает нормально.

(Лично я предпочитаю LINQ to XML использованию XPath, если вы используете .NET 3.5 или выше, но это сработает, если вы предпочитаете использовать XPath.)

РЕДАКТИРОВАТЬ: поведение указано в MSDN: http://msdn.microsoft.com/en-us/library/system.xml.xmlnamespacemanager.addnamespace.aspx как примечание к аргументу «prefix»: «Если XmlNamespaceManager будет использоваться для разрешения пространств имен в выражении языка пути XML (XPath), необходимо указать префикс. Если выражение XPath не содержит префикса, предполагается, что Унифицированный идентификатор ресурса пространства имен (URI) является пустым пространством имен.»

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

1. Спасибо, сработал как шарм! Похоже, вы знаете больше, чем люди, написавшие онлайн-документацию Microsoft, которые предложили string . Пусто 😉

2. Брайан, не забудь принять ответ. Пожалуйста, предоставьте ссылку на «онлайн-документацию …», чтобы кто-нибудь мог это исправить (если это не msdn.microsoft.com/en-us/library/… в котором явно указано «… для разрешения пространств имен в выражении языка пути XML (XPath) должен быть указан префикс …» в примечании к аргументу «prefix»).