#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»).