XPath для XML с пространством имен - PullRequest
5 голосов
/ 16 января 2010

У меня есть xml с различными пространствами имен, которые я хотел бы запросить, используя .SelectNodes (string xPath)

Проблема, которую я заметил, заключается в том, что запрос xPath ничего не возвращает, пока у меня есть все эти пространства имен.

  1. в любом случае можно сказать XmlDocument.SelectNodes игнорировать эти пространства имен и просто получить нужные мне элементы (элементы, к которым я обращаюсь, не имеют префикса пространств имен)?

  2. если есть, кто-нибудь может дать мне пример того, как это сделать? Что я должен определить до / когда я запрашиваю узлы?

Спасибо за помощь.

Исправление: я до сих пор не могу понять, в чем проблема. вот мой xml:

<feed xmlns="http://www.w3.org/2005/Atom"  xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"  xmlns:gf="http://schemas.google.com/finance/2007"  
      xmlns:gd="http://schemas.google.com/g/2005" >
  <id>http://finance.google.com/finance/feeds/xyx@google.com/portfolios</id>
  <updated>2009-12-15T19:32:21.000Z</updated>
  <category scheme="http://schemas.google.com/g/2005#kind"  term="http://schemas.google.com/finance/2007#portfolio" />
  <title type="text" >Portfolio Feed</title>
  <link rel="alternate"  type="text/html"  href="http://finance.google.com/finance/portfolio?action=view" />
  <link rel="http://schemas.google.com/g/2005#feed"  type="application/atom+xml"  href="http://finance.google.com/finance/feeds/default/portfolios" />
  <link rel="http://schemas.google.com/g/2005#post"  type="application/atom+xml"  href="http://finance.google.com/finance/feeds/default/portfolios" />
  <link rel="self"  type="application/atom+xml"  href="http://finance.google.com/finance/feeds/default/portfolios" />
  <openSearch:totalResults>24</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>24</openSearch:itemsPerPage>
  <entry>
    <id>http://finance.google.com/finance/feeds/xyx@google.com/portfolios/2</id>
    <updated>2009-12-14T16:26:53.000Z</updated>
    <category scheme="http://schemas.google.com/g/2005#kind"  term="http://schemas.google.com/finance/2007#portfolio" />
    <title type="text" >Main</title>
    <link rel="self"  type="application/atom+xml"  href="http://finance.google.com/finance/feeds/default/portfolios/2" />
    <link rel="edit"  type="application/atom+xml"  href="http://finance.google.com/finance/feeds/default/portfolios/2" />
    <gd:feedLink href="http://finance.google.com/finance/feeds/xyx@google.com/portfolios/2/positions" />
    <gf:portfolioData currencyCode="USD"  gainPercentage="0.0"  return1w="0.0"  return1y="0.0"  return3m="0.0"  return3y="0.0"  return4w="0.0"  return5y="0.0"  returnOverall="0.0"  returnYTD="0.0" />
  </entry>
</feed>

и вот мой код:

XmlDocument xml = ExecuteRequest (url);

        var xmlnsManager = new System.Xml.XmlNamespaceManager(xml.NameTable);
        xmlnsManager.AddNamespace("xmlns:openSearch", "http://a9.com/-/spec/opensearchrss/1.0/");
        xmlnsManager.AddNamespace("xmlns:gf", "http://schemas.google.com/finance/2007");
        xmlnsManager.AddNamespace("xmlns:gd", "http://schemas.google.com/g/2005");

        var nodes = xml.SelectNodes("//feed/entry", xmlnsManager);

и число моих узлов все еще равно 0! есть идеи?

Ответы [ 3 ]

9 голосов
/ 16 января 2010

Вам необходимо создать менеджер пространства имен, настроить все пространства имен, которые вы хотите использовать, и их префикс, а затем в XPath вам необходимо использовать префикс.

var doc = new XmlDocument(); 
doc.Load("myfile.xml");

var xmlnsManager = new System.Xml.XmlNamespaceManager(doc.NameTable);
xmlnsManager.AddNamespace("ns", "http://example.org/schema.xsd");

doc.SelectNodes("//ns:MyElement",xmlnsManager);

Предупреждение: я не скомпилировал этот код.

2 голосов
/ 16 января 2010

Я не так хорошо знаком с .NET API, но вы можете отправить более общий XPATH, который игнорирует пространства имен, сопоставляя его с любым элементом (например, *) и используя local-name в предикате. фильтры.

например. используя /*[local-name()='foo']/*[local-name()='bar']/*[local-name()='baz'] найти ns:foo/ns:bar/ns:baz без объявления пространства имен ns .

Таким образом, вам не нужно привязываться к определенному пространству имен во время компиляции, и вы можете передавать произвольные операторы XPATH.

Очевидно, что с помощью операторов XPATH, не поддерживающих пространство имен, вы можете получить непредвиденные результаты (если имеется смешанное содержимое пространства имен с элементами с одинаковыми именами), а XPATH действительно многословен.

В XPATH 2.0 вы можете использовать подстановочные знаки для пространств имен: /*:foo/*:bar/*:baz, но вам придется использовать Saxon , чтобы получить поддержку XSLT / XPATH 2.0 в .NET.

0 голосов
/ 18 января 2010

нашел проблему в другом посте здесь: Нет узлов, выбранных из XML-документа Atom с использованием XPath?

спасибо всем.

...