XPath с пространствами имен Xml

Сегодня я потратил очень утомительный час, пытаясь изменить запрос XPath для работы с пространствами имен. Я собираюсь воссоздать этот сценарий и проиллюстрировать, как мы выполняем запрос XPath для документа Xml без пространств имен, а затем выбираем те же данные в документе XML с пространствами имен.

Примечание. В целом мне явно не нравятся пространства имен Xml — полагаю, я мог бы подумать об их использовании, но чаще всего YAGNI .

XPath без пространств имен

<?xml version="1.0" encoding="utf-8" ?>
<books>
  <book title="Harry Potter">
    <author name="J.K. Rowling">Some details about the author</author>
  </book>
  <book title="WPF Unleashed">
    <author name="Adam Nathan" />
  </book>
</books>

Это образец документа, который я создал. Теперь предположим, что мы хотим выбрать сведения об авторе «Гарри Поттера», а также имя автора «WPF Unleashed». Это наиболее распространенный сценарий, с которым я сталкиваюсь при работе с Xml — я вижу нужные данные — мне просто нужно выяснить запрос, чтобы выбрать его.

В этом случае у нас есть 2 простых выражения XPath, которые мы выполняем с использованием класса C # XmlDocument .

var withoutNamespaces = new XmlDocument();
withoutNamespaces.Load("DataWithoutNamespaces.xml");

withoutNamespaces.SelectSingleNode("/books/book[@title='Harry Potter']/author").InnerText
withoutNamespaces.SelectSingleNode("/books/book[@title='WPF Unleashed']/author/@name").Value

Это работает как ожидалось. Теперь давайте сделаем то же самое для документа с пространствами имен Xml.

XPath с пространствами имен

<?xml version="1.0" encoding="utf-8" ?>
<books xmlns="http://www.amazon.com">
  <book xmlns="http://www.amazon.com/HarryPotter" title="Harry Potter">
    <author name="J.K. Rowling">Some details about the author</author>
  </book>
  <book title="WPF Unleashed">
    <author name="Adam Nathan" />
  </book>
</books>

Таким образом, у нас есть те же данные, что и раньше, но наши запросы XPath больше не смогут их выбрать. Вы даже не сможете выбрать корневой узел — каждый запрос просто вернет ноль .

Чтобы иметь возможность указывать пространства имен для наших запросов XPath, нам нужно использовать класс C # XmlNamespaceManager и передать это как перегрузку методу SelectSingleNode . Вам необходимо создать псевдоним для каждого пространства имен, а затем использовать этот псевдоним в качестве префикса для каждого элемента, который наследует пространство имен.

var withNamespaces = new XmlDocument();
withNamespaces.Load("DataWithNamespaces.xml");

var namespaceManager = new XmlNamespaceManager(withNamespaces.NameTable);
namespaceManager.AddNamespace("ama", "http://www.amazon.com");
namespaceManager.AddNamespace("pot", "http://www.amazon.com/HarryPotter");

withNamespaces.SelectSingleNode("/ama:books/pot:book[@title='Harry Potter']/pot:author", namespaceManager).InnerText
withNamespaces.SelectSingleNode("/ama:books/ama:book[@title='WPF Unleashed']/ama:author/@name", namespaceManager).Value

Обратите внимание на использование префикса ‘pot’ в первом элементе author и ‘ama’ во втором элементе author — поскольку эти элементы не имеют явных пространств имен, пространства имен наследуются. Также обратите внимание, что селектор атрибута ‘name’ не имеет префикса пространства имен — только элементы наследуют пространства имен.

Надеюсь, это кому-нибудь поможет

Интернет по оптике в Миассе AirNet

Author: admin

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *