2011-01-19 2 views
2

При выборе из XmlDocument, например. XPath-method SelectSingleNode мы получаем XmlNode, который состоит из первого совпадающего узла, позволяет называть его <node1>. Если мы сделаем дальнейший отбор на <node1>, тогда можно было бы ожидать, что теперь этот узел является корнем XPath, но это неверно, корень все тот же, что и в исходном XmlDocument. Вот пример:Измените XPath-корень XmlDocument в .net (C#)?

XmlDocument xd = new XmlDocument(); 
xd.LoadXml(@"<root> 
       <subroot> 
        <elm>test1</elm> 
        <elm>test2</elm> 
        <elm>test3</elm> 
       </subroot> 
      </root>"); 
XmlNode xnSubRoot = xd.SelectSingleNode("/root/subroot"); 

//This is the XPath I want to be able to use, but it returns null. 
XmlNode xnElm = xnSubRoot.SelectSingleNode("/subroot/elm"); 

//This works, but the XPath-root is the same as in the original document. 
xnElm = xnSubRoot.SelectSingleNode("/root/subroot/elm"); 

Есть ли способ, чтобы «исправить» корень xnSubRoot так, что я могу использовать XPath я хочу? Причина моего вопроса заключается в том, что у меня есть случай, когда я вызываю веб-службу, которая возвращает XmlNode, где свойство OuterXml показывает структуру «/ Data/SubElement/...» и т. Д., Но при запуске XPath "/Data ", тогда возвращается null, работает только«/SubElement », т. Е. Корень XPath кажется на один уровень ниже, чем фактический корень документа.

Я уверен, что для этого есть вполне разумное объяснение, или что мне не хватает чего-то жизненно важного. Однако я действительно ничего не могу найти, хотя я читал http://msdn.microsoft.com/en-us/library/d271ytdx(VS.80).aspx.

N.B. Я понимаю, что можно было бы использовать XPath «// subroot/elm», но тогда я мог бы также добавить другие элементы в структуру XML.

ответ

2

Поскольку ваш выбирающий из Root/SubElement Попробуйте это:

XmlNode xnElm = xnSubRoot.SelectSingleNode("elm"); 

Это возвратит первый ребенок elm узел текущего узла.

Edit (из информаций, предоставленных Дополнительных условий в комментариях):

В данном конкретном случае, вы obtaning XmlNode (что ваш узел данных) от WebService вызова. Все запросы XPath по этому адресу XmlNode будут относиться к нему.

Я предлагаю вам изменить все ваши XPaths, чтобы использовать селектор, например webServiceNode.SelectSingleNode("SubElement/SubSubElement");. Здесь нет причин указывать абсолютные запросы XPaths.

+0

Спасибо, что вы правы, конечно, когда речь идет о примере, который я дал. Но как насчет того, когда XPath-root на самом деле ниже, чем корень документа? Я не уверен, как это может быть, но это тот случай с XMLNode, который я получаю из webservice. –

+0

Можете ли вы предоставить образец своего веб-сервиса Xml? –

+0

Я использовал функцию «Добавить веб-ссылку» в VS2005 для автоматического создания кода для вызова веб-службы. Этот код вызывает System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke (string, object []), который возвращает объект [], а затем явно задает объект [0] в XmlNode. Что касается XML, извините, но я не могу показать его здесь, но структура документа . Однако при запуске XPath на нем корневой/SubElement, а не ожидаемый,/Data (то есть SelectSingleNode ("/ Data") возвращает значение null, но SelectSingleNode ("/ SubElement") работает). –

2

Это работает:

XmlNode xnSubRoot = xd.SelectSingleNode("/root/subroot"); 
XmlNode xnElm = xnSubRoot.SelectSingleNode("elm"); 

И так же это:

XmlNode xnRoot = xd.SelectSingleNode("/root"); 
XmlNode xnElm = xnRoot.SelectSingleNode("subroot/elm"); 
+0

Спасибо, ты прав, конечно, когда дело доходит до примера, который я дал. Но как насчет того, когда XPath-root на самом деле ниже, чем корень документа? Я не уверен, как это может быть, но это тот случай с XMLNode, который я получаю из webservice. –

+0

Полученный вами XmlNode не имеет родительского узла и вызывает поведение, которое вы видите. Каждый узел работает только со структурой, показанной свойством InnerXml. Если вы хотите сделать то же самое с вашим примером, вы можете сделать «xnSubRoot = xnSubRoot.CloneNode (true)». Это может быть не лучшее решение, но, по крайней мере, это работает. Тем не менее, мне интересно, почему вы хотите использовать запросы XPath, основанные на корне (например, начинать с '/')? – mgronber

Смежные вопросы