XPath: выберите узел, не извлекая его дочерние элементы

#xml #xpath

#xml #xpath

Вопрос:

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

 <parentnode>
  <node1 a="b" b="c">
    <child1/>
    <child2/>
    ... many many child nodes
    <childN/>
  </node1>
  <node2/>
</parentnode>
  

Я хотел бы иметь возможность выбирать элемент ‘node1’ для проверки его атрибутов, но без выбора дочерних узлов, которые мне не нужно анализировать и которые могут состоять из тысяч элементов, что влияет на производительность запроса (выходные данные которого используются для построения своего рода дерева DOM с массивами и словарями в сторонней библиотеке).

Обновление: чтобы было понятнее, упомянутая мной сторонняя библиотека на самом деле является просто оболочкой Objective-C вокруг анализатора libxml2, который создает DOM-дерево из базовых классов с результатом любого запроса XPath. Сами запросы выполняются над уже проанализированным документом (xmlDocPtr), который повторно используется для всех запросов, так что да, как говорится во многих ответах, документ уже размещен на уровне C, но реализация Objective-C wrapper приводит к снижению производительности в этом конкретном сценарии. Я мог бы изменить эту библиотеку, чтобы при необходимости не извлекать дочерние элементы выбранного узла, но я подумал, что, вероятно, будет простой способ получить только атрибуты узла с помощью запроса.

Ответ №1:

Выражение XPath, такое как /a / b / c, выберет элементы c: оно не выбирает их дочерние элементы. Причина, по которой многие люди воображают, что он также выбирает дочерние элементы, заключается в том, что многие инструменты будут показывать результат выражения XPath, показывая вам все поддерево с корнем в элементе c. Можно понять, почему они это делают — это визуально показывает вам, что вы выбрали, — но само выражение XPath просто возвращает указатель на выбранный элемент, и куда вы идете оттуда, полностью зависит от вас. (Некоторые инструменты, вместо того, чтобы показывать вам поддерево с корнем в элементе, показывают путь к узлу со всеми его предками — это одинаково допустимо.)

Комментарии:

1. Действительно, вы очень правы. Это сторонняя библиотека, которая создает свое собственное дерево DOM с корнем на выбранном узле. Изначально я не объяснил это должным образом и с тех пор обновил вопрос. Спасибо.

Ответ №2:

Если вам нужны только атрибуты, тогда просто выберите атрибуты: /parentnode/node1/@*

Но (как отмечено в другом ответе) и процессору Xpath все равно приходится анализировать весь файл. Вы не будете экономить много.

Если вы хотите проанализировать только часть файла, а затем остановиться после получения необходимой информации, вам, вероятно, следует использовать SAX или какой-либо другой API, который дает вам более низкий уровень управления синтаксическим анализом.

Комментарии:

1. Спасибо, это именно то, что мне было нужно, чтобы получить только атрибуты. В вопросе я дополнительно разъяснил, откуда взялся спад производительности.

Ответ №3:

используйте @, например, для получения атрибутов:

  • /parentnode/node1/@a — получит значение «b»
  • /parentnode/node1/@b — получит значение «c»

Ответ №4:

Что ж, если все это уже настроено DOM’d, то вы не выполняете дальнейшее DOMing, выбрав XPATH node1. На этом этапе тот факт, что у node1 есть дочерние элементы, не имеет отношения к производительности.

Однако, если мы предполагаем, что все это не является DOM’d up, то мы, вероятно, говорим о считывателе только для пересылки. Есть несколько программ чтения только с пересылкой, которые могут выполнить необходимый вам XPATHing.