XPathNavigator может выбирать тестовый ввод, но не реальный ввод

Вот мой XML, полученный при печати serviceListXml на консоль, как показано в коде ниже:

<?xml version="1.0" encoding="utf-8"?>
<service xml:base="https://fnord/live/api/v1" xmlns="http://www.w3.org/2007/app" xmlns:atom="http://www.w3.org/2005/Atom">
  <workspace>
    <atom:title type="text">Service List</atom:title>
    <collection href="Erp.BO.ABCCodeSvc">
      <atom:title type="text">Erp.BO.ABCCodeSvc</atom:title>
    </collection>
    <collection href="Erp.BO.AccountBudgetSvc">
      <atom:title type="text">Erp.BO.AccountBudgetSvc</atom:title>
    </collection>
    <collection href="Erp.BO.ACTTypeSvc">
      <atom:title type="text">Erp.BO.ACTTypeSvc</atom:title>
    </collection>
    <!-- hundreds more collection elements -->
  </workspace>
</service>

И вот мой код:

var serviceListXml = client.GetStringAsync(serviceListUrl).GetAwaiter().GetResult();
//serviceListXml = "<foo><bar><collection/><collection/><collection/></bar></foo>";
Console.WriteLine(serviceListXml);
var doc = new XPathDocument(new StringReader(serviceListXml));
var nav = doc.CreateNavigator();
var foo = nav.Select("//collection");
Console.WriteLine("selected " + foo.Count + " elements");

Это выбирает 0 элементов. Зачем?

Если я раскомментирую строку, которая устанавливает serviceListXml к тестовой строке он находит 3 элемента, как и ожидалось. Я думал, что в моем настоящем XML может быть спецификация, поэтому я попытался использовать serviceListXml.Substring(serviceListXml.IndexOf("<")) но это не имело значения.

1 ответ

Решение

Это потому, что в вашей оригинальной коллекции XML находится в http://www.w3.org/2007/app пространство имен, которое является пространством имен по умолчанию для этого XML. Чтобы иметь возможность выбрать collection Элемент у вас есть два варианта:

Вариант 1: передать пространство имен в ваш XPathDocument, например:

var ns = new XmlNamespaceManager(nav.NameTable);
ns.AddNamespace("ns", "http://www.w3.org/2007/app");
var foo = nav.Select("//ns:collection", ns);

Вариант 2. Используйте этот XPath: var foo = nav.Select("//*[local-name() = 'collection']");

Другие вопросы по тегам