Справка XPathNavigator

Вот образец XML, с которым я работаю (его можно получить из результатов Special: Export / SomePage любой вики):

<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.4/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.4/ http://www.mediawiki.org/xml/export-0.4.xsd" version="0.4" xml:lang="en"> 
  <siteinfo> 
    <sitename>Wikipedia</sitename> 
    <base>http://en.wikipedia.org/wiki/Main_Page</base> 
    <generator>MediaWiki 1.16wmf4</generator> 
    <case>first-letter</case> 
    <namespaces> 
      <namespace key="-2" case="first-letter">Media</namespace> 
      <namespace key="-1" case="first-letter">Special</namespace> 
      <namespace key="0" case="first-letter" /> 
      ...
    </namespaces> 
  </siteinfo> 
</mediawiki> 

Я пробовал все, что мог придумать, чтобы «перейти» непосредственно к узлу siteinfo и повторить результаты, и ничего не работает, если я не прохожу вручную по каждому дочернему узлу от корня вниз. Я пробовал миллион вариантов различных методов .Move * и .Select *, и мне кажется, что я просто бьюсь головой об стену, но мой текущий вариант выглядит так:

StringReader strr = new StringReader(_rawData);
XPathDocument xd = new XPathDocument(XmlReader.Create(strr, Bot.XmlReaderSettings));
XPathNavigator xn = xd.CreateNavigator();
XPathNodeIterator xni = xn.Select("/mediawiki/siteinfo");
foreach (XPathNavigator nav in xni)
    Console.WriteLine(nav.LocalName);

Это не дает результатов. Что я делаю неправильно?


person Community    schedule 14.11.2010    source источник


Ответы (1)


Добро пожаловать в пространства имен XML. Вам необходимо создать сопоставление между префиксом и xmlns корневого элемента. Например, у меня сработал этот код:

using (var r = File.OpenText("test.xml")) {
    XPathDocument xd = new XPathDocument(XmlReader.Create(r));
    XPathNavigator xn = xd.CreateNavigator();

    XmlNamespaceManager nsmgr = new XmlNamespaceManager(xn.NameTable);
    nsmgr.AddNamespace("mw", "http://www.mediawiki.org/xml/export-0.4/");

    XPathNodeIterator xni = xn.Select("/mw:mediawiki/mw:siteinfo", nsmgr);

    foreach (XPathNavigator nav in xni)
        Console.WriteLine(nav.Name);
}

Дополнительное чтение, если вам интересно: MSDN: пространства имен XML и их влияние на XPath и XSLT.

person cdhowie    schedule 14.11.2010
comment
Для дополнительных бонусных баллов можно ли определить URL-адрес пространства имен с помощью XPathNavigator, или я должен просто использовать Regex, поскольку у меня все равно есть строка заранее? - person ; 15.11.2010
comment
Ничего страшного, я сам это понял: xn.MoveToFirstChild (); nsmgr.AddNamespace (mw, xn.NamespaceURI); - person ; 15.11.2010