Существует ли какой-нибудь пакет для Ubuntu и / или CentOS, в котором есть инструмент командной строки, который может выполнять однострочное выполнение XPath foo //element@attribute filename.xml
или foo //element@attribute < filename.xml
возвращать результаты построчно?
Я ищу что-то, что позволило бы мне просто apt-get install foo
или yum install foo
просто работать из коробки, без обертки или другой необходимой адаптации.
Вот несколько примеров таких вещей:
Nokogiri. Если я напишу эту оболочку, я мог бы вызвать оболочку так, как описано выше:
#!/usr/bin/ruby
require 'nokogiri'
Nokogiri::XML(STDIN).xpath(ARGV[0]).each do |row|
puts row
end
XML :: XPath. Будет работать с этой оберткой:
#!/usr/bin/perl
use strict;
use warnings;
use XML::XPath;
my $root = XML::XPath->new(ioref => 'STDIN');
for my $node ($root->find($ARGV[0])->get_nodelist) {
print($node->getData, "\n");
}
xpath
из XML :: XPath возвращает слишком много шума, -- NODE --
и attribute = "value"
.
xml_grep
из XML :: Twig не может обрабатывать выражения, которые не возвращают элементы, поэтому не может использоваться для извлечения значений атрибутов без дальнейшей обработки.
РЕДАКТИРОВАТЬ:
echo cat //element/@attribute | xmllint --shell filename.xml
возвращает шум, похожий на xpath
.
xmllint --xpath //element/@attribute filename.xml
возвращается attribute = "value"
.
xmllint --xpath 'string(//element/@attribute)' filename.xml
возвращает то, что я хочу, но только для первого матча.
Для другого решения, почти удовлетворяющего этот вопрос, вот XSLT, который можно использовать для оценки произвольных выражений XPath (требуется поддержка dyn: define в процессоре XSLT):
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:dyn="http://exslt.org/dynamic" extension-element-prefixes="dyn">
<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
<xsl:template match="/">
<xsl:for-each select="dyn:evaluate($pattern)">
<xsl:value-of select="dyn:evaluate($value)"/>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Беги с xsltproc --stringparam pattern //element/@attribute --stringparam value . arbitrary-xpath.xslt filename.xml
.
источник
xpath
находится на STDERR, а не на STDOUT.Ответы:
Вы должны попробовать эти инструменты:
xmlstarlet
: можно редактировать, выбирать, преобразовывать ... Не установлено по умолчанию, xpath1xmllint
: Часто устанавливается по умолчанию сlibxml2-utils
, xpath1 (проверьте мою оболочку , чтобы иметь--xpath
переключатель на очень старых релизов и новых строк с разделителями выход (v <2.9.9)xpath
: устанавливается через модуль PerlXML::XPath
, xpath1xml_grep
: устанавливается через модуль PerlXML::Twig
, xpath1 (ограниченное использование xpath)xidel
: xpath3saxon-lint
: мой собственный проект, обертка над Java-библиотекой Saxon-HE @Michael Kay, xpath3xmllint
поставляется сlibxml2-utils
(может использоваться как интерактивная оболочка с--shell
переключателем)xmlstarlet
естьxmlstarlet
.xpath
поставляется с модулем PerlXML::Xpath
xml_grep
поставляется с модулем PerlXML::Twig
xidel
являетсяxidel
saxon-lint
использование SaxonHE 9.6 , XPath 3.x (+ ретро-совместимость)Пример:
,
источник
xmlstarlet sel -T -t -m '//element/@attribute' -v '.' -n filename.xml
делает именно то, что я хочу!xmllint
не поддерживают аргумент командной строки--xpath
, но большинство, похоже, поддерживают--shell
. Небольшой грязный вывод, но все же полезный в безвыходном положении.sel -t -m ... -v ...
примером на этой странице: arstechnica.com/information-technology/2005 / 11 / linux-20051115/2 , сопоставляя все, кроме последнего узла, и сохраняя его для выражения значения, такого как мойВы также можете попробовать мой Xidel . Его нет в пакете в репозитории, но вы можете просто загрузить его с веб-страницы (он не имеет зависимостей).
Он имеет простой синтаксис для этой задачи:
И это один из редких инструментов, который поддерживает XPath 2.
источник
Один пакет, который, вероятно, будет установлен в системе, уже есть
python-lxml
. Если это так, это возможно без установки какого-либо дополнительного пакета:источник
stdin
. Это исключает необходимость включенияopen()
иclose()
в уже достаточно длинную строчку. Для разбора файла просто запустите,python -c "from lxml.etree import parse; from sys import stdin; print '\n'.join(parse(stdin).xpath('//element/@attribute'))" < my_file.xml
и пусть ваша оболочка обработает поиск, открытие и закрытие файла.В своем поиске по запросу файлов maven pom.xml я столкнулся с этим вопросом. Однако у меня были следующие ограничения:
Я попробовал многие из вышеперечисленных без успеха:
Решение, с которым я столкнулся, является стабильным, коротким и работает на многих платформах, а также является зрелым, это встроенная в ruby библиотека rexml lib:
Что вдохновило меня на поиск этой статьи, так это следующие статьи:
источник
xmlstarlet
принятого ответа, потому что он соответствует моим более широким критериям и действительно опрятен . Но я, вероятно, буду время от времени использовать ваше решение.puts
вместо командыp
Ruby.Саксон сделает это не только для XPath 2.0, но и для XQuery 1.0 и (в коммерческой версии) 3.0. Это не пакет Linux, а файл JAR. Синтаксис (который вы можете легко обернуть в простой сценарий)
ОБНОВЛЕНИЕ 2020
Saxon 10.0 включает в себя инструмент Gizmo, который можно использовать в интерактивном режиме или в пакетном режиме из командной строки. Например
источник
libsaxonb-java
, но если я бегуsaxonb-xquery -qs://element/@attribute -s:filename.xml
яSENR0001: Cannot serialize a free-standing attribute node
, та же проблема , как и , напримерxml_grep
.-qs
так:'-qs:declare namespace mets="http://www.loc.gov/METS/";/mets:mets/mets:dmdSec'
Вы также можете быть заинтересованы в xsh . Он имеет интерактивный режим, в котором вы можете делать с документом все, что захотите:
источник
cpan XML::XSH2
.cpan XML::XSH2
ничего не устанавливается.Ответ clacke отличный, но я думаю, что он работает только в том случае, если ваш источник - правильно сформированный XML, а не обычный HTML.
Таким образом, чтобы сделать то же самое для обычного веб-контента - документов HTML, которые не обязательно являются правильно сформированным XML:
И вместо этого использовать html5lib (чтобы гарантировать, что вы получаете то же самое поведение при разборе, что и веб-браузеры - потому что, как и парсеры браузеров, html5lib соответствует требованиям синтаксического анализа в спецификации HTML).
источник
Как и в ответах Майка и Клака, здесь приведен однострочный вкладыш python (использующий python> = 2.5) для получения версии сборки из файла pom.xml, который позволяет обойти тот факт, что файлы pom.xml обычно не имеют dtd или пространство имен по умолчанию, так что не выглядите правильно в libxml:
Протестировано на Mac и Linux и не требует установки дополнительных пакетов.
источник
lxml
ниxmllint
, ни даже Ruby. В духе формата в своем собственном ответе я написал это какpython3 -c "from xml.etree.ElementTree import parse; from sys import stdin; print(parse(stdin).find('.//element[subelement=\"value\"]/othersubelement').text)" <<< "$variable_containing_xml"
в bash..getroot()
не кажется необходимым.В дополнение к XML :: XSH и XML :: XSH2 есть некоторые
grep
подобные утилиты suck asApp::xml_grep2
иXML::Twig
(которые включают в себя,xml_grep
а неxml_grep2
). Они могут быть весьма полезны при работе с большими или многочисленными XML-файлами для быстрых ссылок илиMakefile
целей.XML::Twig
Особенно приятно работать соperl
сценарием, когда вы хотите немного больше обработки, чем вы$SHELL
иxmllint
xstlproc
предлагаете.Схема нумерации в именах приложений указывает на то, что «2» версии являются более новой / более поздней версией, по сути, того же инструмента, для которого могут потребоваться более поздние версии других модулей (или самих
perl
себя).источник
xml_grep2 -t //element@attribute filename.xml
работает и делает то, что я ожидаю (xml_grep --root //element@attribute --text_only filename.xml
до сих пор нет, возвращает ошибку «нераспознанное выражение»). Большой!xml_grep --pretty_print --root '//element[@attribute]' --text_only filename.xml
? Не уверен, что там происходит или о чем говорит XPath[]
в этом случае, но окружение@attribute
с квадратными скобками работает дляxml_grep
иxml_grep2
.//element/@attribute
, нет//element@attribute
. Очевидно, что редактировать его не могу, но оставив его там вместо удаления + замены, чтобы не запутать историю этого обсуждения.//element[@attribute]
выбирает элементы типа,element
которые имеют атрибутattribute
. Я не хочу элемент, только атрибут.<element attribute='foo'/>
должен дать мнеfoo
, а не полный<element attribute='foo'/>
.--text_only
в этом контексте дает мне пустую строку в случае элемента, как<element attribute='foo'/>
без текстового узла внутри.Стоит упомянуть, что сам nokogiri поставляется с инструментом командной строки, который должен быть установлен вместе с
gem install nokogiri
.Вы можете найти этот пост полезным .
источник
Я попробовал несколько утилит командной строки XPath и, когда понял, что слишком много времени гуглю и выясняю, как они работают, я написал простейший парсер XPath на Python, который сделал то, что мне было нужно.
Сценарий ниже показывает строковое значение, если выражение XPath вычисляется как строку, или показывает весь подузел XML, если результатом является узел:
Он использует
lxml
быстрый синтаксический анализатор XML, написанный на C, который не включен в стандартную библиотеку python. Установите его с помощьюpip install lxml
. В Linux / OSX может потребоваться префикс сsudo
.Использование:
lxml также может принимать URL в качестве входных данных:
Извлеките атрибут URL - адрес под вольер узел т.е.
<enclosure url="http:...""..>)
:Xpath в Google Chrome
В качестве несвязанного примечания: если вы случайно захотите запустить выражение XPath для разметки веб-страницы, то вы можете сделать это прямо из Chrome devtools: щелкните правой кнопкой мыши страницу в Chrome> выберите Inspect, а затем в DevTools консоль вставьте ваше выражение XPath как
$x("//spam/eggs")
.Получить всех авторов на этой странице:
источник
lxml
уже упоминалось в двух других ответах за годы до вашего.Вот один пример использования xmlstarlet для извлечения данных из вложенных элементов elem1, elem2 в одну строку текста из этого типа XML (также показано, как обрабатывать пространства имен):
Выход будет
В этом фрагменте -m соответствует вложенному элементу elem2, -v выводит значения атрибутов (с выражениями и относительной адресацией), -o литеральный текст, -n добавляет новую строку:
Если от elem1 требуется больше атрибутов, это можно сделать так (также показывая функцию concat ()):
Обратите внимание на сложность (ненужную IMO) с пространствами имен (ns, объявленной с -N), из-за которой я почти разочаровался в xpath и xmlstarlet, и написание быстрого специального конвертера.
источник
Мой скрипт на Python xgrep.py делает именно это. Для поиска всех атрибутов
attribute
элементовelement
в файлахfilename.xml ...
вы должны выполнить его следующим образом:Существуют различные переключатели для управления выводом, например,
-c
для подсчета совпадений,-i
для отступа соответствующих частей и только-l
для вывода имен файлов.Сценарий недоступен в виде пакета Debian или Ubuntu, но все его зависимости доступны.
источник
Поскольку этот проект, по-видимому, довольно новый, ознакомьтесь с https://github.com/jeffbr13/xq, который , похоже, является оберткой
lxml
, но это все, что вам действительно нужно (и опубликовал специальные решения, использующие lxml и в других ответах).источник
Я не был доволен однострочниками Python для запросов HTML XPath, поэтому я написал свой собственный. Предполагается, что вы установили
python-lxml
пакет или запустилиpip install --user lxml
:Если у вас есть его, вы можете использовать его, как в этом примере:
источник
Установите базу данных BaseX , затем используйте ее «автономный режим командной строки» следующим образом:
basex -i - //element@attribute < filename.xml
или
basex -i filename.xml //element@attribute
На самом деле языком запросов является XQuery (3.0), а не XPath, но поскольку XQuery является расширенным набором XPath, вы можете использовать запросы XPath, даже не заметив этого.
источник