Неправильный xml-узел, доступный при использовании xpath - PullRequest
0 голосов
/ 01 октября 2018

У меня есть XML-файл, созданный Vector CANeds.Этот файл содержит информацию об объектах CANopen, которые я хочу прочитать с помощью своего инструмента, написанного на C #.

(очень базовая) структура xml выглядит следующим образом:

<ISO15745ProfileContainer xmlns="http://www.canopen.org/xml/1.0">
    <ISO15745Profile>
        <ProfileHeader></ProfileHeader>
        <ProfileBody xsi:type="ProfileBody_Device_CANopen"</ProfileBody>
    </ISO15745Profile>
    <ISO15745Profile>
        <ProfileHeader></ProfileHeader>
        <ProfileBody xsi:type="ProfileBody_CommunicationNetwork_CANopen"</ProfileBody>
    </ISO15745Profile>
</ISO15745ProfileContainer>

Когда я создаюXmlNodeList с обоими узлами ISO15745Profile в нем и циклом, тогда я получаю странное поведение.Получая доступ к подузлам с явными индексами, все как и ожидалось.Когда я использую xpath, всегда используется первый узел.

Фрагмент кода:

const string filepath = "CANeds1.xdd";
const string s_ns = "//ns:";
var mDataXML = new XmlDocument();
mDataXML.Load(filepath);
var root = mDataXML.DocumentElement;
XmlNamespaceManager nsm = new XmlNamespaceManager(mDataXML.NameTable);
nsm.AddNamespace("ns", root.Attributes["xmlns"].Value);

foreach (XmlNode node in root.ChildNodes) {
    Console.WriteLine("  " + node.ChildNodes[1].Attributes["xsi:type"].Value);
    Console.WriteLine("  " + node.SelectSingleNode(s_ns + "ProfileBody", nsm).Attributes["xsi:type"].Value);
}

Вывод на консоль:

  ProfileBody_Device_CANopen
  ProfileBody_Device_CANopen
  ProfileBody_CommunicationNetwork_CANopen
  ProfileBody_Device_CANopen

Поскольку узел ссылается на 2-й узел,последний вывод должен быть commNetwork to.Кто-нибудь видит мою ошибку?Я уже пытался переименовать один из узлов «ISO15745Profile», но это не изменило результат.Возможно, я что-то напутал с пространством имен ...

1 Ответ

0 голосов
/ 01 октября 2018

Еще несколько пояснений к ответу, приведенному в комментариях:

Важным моментом является выражение // XPath.Определение из MSDN гласит:

рекурсивный спуск;ищет указанный элемент на любой глубине.Когда этот оператор пути появляется в начале шаблона, он указывает на рекурсивный спуск из корневого узла .

Это означает, что выражение, начинающееся с //, всегда будет искать вхождения весь документ , даже если он вызывается из определенной дочерней заметки.Вот почему SelectSingleNode всегда будет возвращать первое совпадение во всем документе.

Для поиска относительно узла, вызывающего метод выбора, существует оператор ., который указывает текущий контекст.

Если сложить, выражение, начинающееся с .//, будет искать все вхождения следующего шаблона, начиная с текущего узла .

В конкретном случае это означает изменение //ns: до .//ns:, чтобы получить ожидаемый результат.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...