Расширенный поиск с помощью xpath
Во второй части руководства вы потратите некоторое время на поиск в строке XML, используя выражения xpath с функцией xml_find_all().
Добавление дополнительных атрибутов
В первой части руководства по XML обработке с помощью R вы создали объект book_catalog, который указывает на строку XML, представляющую каталог из трех книг, являющихся родительскими узлами для пяти элементов, описывающих различные аспекты каждой книги. Наконец, каждая книга имеет один атрибут id, который служит средством идентификации книги. На этот раз мы будем работать с немного измененной версией book_catalog, enhanced_book_catalog, которая объединяет информацию о трех дочерних узлах -author, title и price в качестве атрибутов в начальных тегах узлов book (см. части начальных тегов ниже). Этот тип изменения может быть частью выбора дизайна схемы аннотации XML и может быть направлен на лучшее отражение реальности книжного каталога.
# Creating an XML string
enhanced_book_catalog <- '<catalog>
<book id="bk101" author="Gambardella, Matthew" title="XML Developer\'s Guide" price="44.95">
<genre>Computer</genre>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications
with XML.</description>
</book>
<book id="bk102" author="Ralls, Kim" title="Midnight Rain" price="5.95">
<genre>Fantasy</genre>
<publish_date>2000-12-16</publish_date>
<description>A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.</description>
</book>
<book id="bk103" author="Corets, Eva" title="Maeve Ascendant" price="5.95">
<genre>Fantasy</genre>
<publish_date>2000-11-17</publish_date>
<description>After the collapse of a nanotechnology
society in England, the young survivors lay the
foundation for a new society.</description>
</book>
</catalog>'
Давайте разберем новую строку XML в новый объект R с помощью функции xml_parse() библиотеки xml2, как мы делали в прошлый раз.
# Loading the xml2 > library(xml2) # Reading the XML string into an R object. > parsed_enhanced_book_catalog <- read_xml(enhanced_book_catalog)
Поиск XML с помощью xml_find_all() and xpath
Если вам нужно получить определенный элемент в DOM, вы можете использовать пошаговый поиск, который вы видели в первой части. Однако чаще всего запрос строки XML для всех элементов, которые соответствуют определенному критерию, является распространенным сценарием перед количественной оценкой появления определенных элементов и их атрибутов.
Для обработки таких запросов вы можете использовать функцию xml_find_all(), предоставляемую пакетом xml2, который использует преимущества языка xpath. Xpath — это язык выражений, который поможет вам реализовать очень сложные поисковые запросы.
Есть два способа поиска по DOM с xpath выражениями. Вы либо должны указать абсолютный путь к DOM местоположению узла, либо вы можете использовать нечеткий поиск, используя двойную косую черту, //, перед элементом и/или любые другие критерии, которые вы хотите, такие как атрибуты и их значений, как вы увидите в следующем разделе.
Использование абсолютных путей к узлам
Давайте задействуем функцию xml_find_all() для поиска в наборах узлов с использованием абсолютных путей. Первым аргументом функции является проанализированная строка XML, а вторым аргументом — строка с выражением xpath. В следующей строке кода выражение xpath указывает путь, начинающийся от корневого узла /, следующий за дочерним узлом catalog и заканчивающийся набором узлов book. Обратите внимание, что последняя часть пути, а именно book, указывает не на один конкретный book, а на все три узла book под узлом catalog. другими словами, любое выражение xpath может указывать на уровень дерева DOM, который включает набор узлов, а не на конкретный узел.
> xml_find_all(parsed_enhanced_book_catalog, "/catalog/book")
{xml_nodeset (3)}
[1] <book id="bk101" author="Gambardella, Matthew" title="XM ...
[2] <book id="bk102" author="Ralls, Kim" title="Midnight Rai ...
[3] <book id="bk103" author="Corets, Eva" title="Maeve Ascen ...
Использование нечеткого поиска
Второй распространенный сценарий — это когда вас интересует элемент узла независимо от его местоположения в DOM. В этом случае вы можете использовать двойную косую черту перед именем интересующего вас элемента, как показано ниже. genre_nodes — это набор узлов жанров, к которым принадлежат три книги. Затем вы также можете извлечь текст из этих узлов, просто используя функцию text(), как вы уже видели в предыдущей части.
> genre_nodes <- xml_find_all(parsed_enhanced_book_catalog, "//genre")
{xml_nodeset (3)}
[1] <genre>Computer</genre>
[2] <genre>Fantasy</genre>
[3] <genre>Fantasy</genre>
# Getting the
> xml_text(xml_find_all(parsed_enhanced_book_catalog, "//genre"))
Вы также можете получить все текстовое содержимое, включенное в любой узел в наборе узлов со звездочкой, как показано ниже для текста во всех элементах любого любого узла book.
> xml_find_all(parsed_enhanced_book_catalog, "//book/*") [1] "Computer" [2] "2000-10-01" [3] "An in-depth look at creating applications \nwith XML." [4] "Fantasy" [5] "2000-12-16" [6] "A former architect battles corporate zombies, \nan evil sorceress, and her own childhood to become queen \nof the world." [7] "Fantasy" [8] "2000-11-17" [9] "After the collapse of a nanotechnology \nsociety in England, the young survivors lay the \nfoundation for a new society."
Запрос с условиями
Xpath выражения позволяют использовать запросы, вводящие условия. Например, вы можете искать узлы с определенным атрибутом, добавляя символ @, за которым следует имя атрибута в квадратных скобках после имени узла. В следующей строке кода возвращаемый набор узлов включает все узлы book, имеющие атрибут title. Выходные данные включают все три узла book, поскольку все они имеют определенный атрибут.
> xml_find_all(parsed_enhanced_book_catalog, "//book[@title]")
{xml_nodeset (3)}
[1] <book id="bk101" author="Gambardella, Matthew" title="XM ...
[2] <book id="bk102" author="Ralls, Kim" title="Midnight Rai ...
[3] <book id="bk103" author="Corets, Eva" title="Maeve Ascen ...
Кроме того, вы также можете запросить строку XML для элементов в определенных позициях, используя xpath expressions.
# Retrieving the last of the elements in the same level at the DOM tree.
> xml_find_all(parsed_enhanced_book_catalog, "//book[last()]")
{xml_nodeset (1)}
[1] <book id="bk103" author="Corets, Eva" title="Maeve Ascen ...
# Retrieving the first two book nodes.
xml_find_all(parsed_enhanced_book_catalog, "//book[position()<3]")
{xml_nodeset (2)}
[1] <book id="bk101" author="Gambardella, Matthew" title="XM ...
[2] <book id="bk102" author="Ralls, Kim" title="Midnight Rai ...
Наконец, вы можете создавать сложные запросы, комбинируя несколько условий с логическими операторами, такими как and и or, как показано ниже:
# Return all books by Kim Ralls that cost less than 10 Euros.
> xml_find_all(parsed_enhanced_book_catalog, "//book[@author='Ralls, Kim' and @price<'10']")
{xml_nodeset (1)}
[1] <book id="bk102" author="Ralls, Kim" title="Midnight Rai ...
Больше замечательных примеров R в действии см. в разделах R-блогеры и R-пользователи.
Далее — от строк/файлов XML к фреймам данных R — Часть III