Эквивалент Grep и Sed для обработки командной строки XML
При выполнении сценариев оболочки, как правило, данные будут находиться в файлах однострочных записей, таких как CSV. Это действительно просто обрабатывать эти данные с grep
а также sed
, Но мне часто приходится иметь дело с XML, поэтому мне бы очень хотелось, чтобы скрипт мог получить доступ к этим XML-данным через командную строку. Каковы лучшие инструменты?
12 ответов
Я нашел, что xmlstarlet довольно хорош в подобных вещах.
http://xmlstar.sourceforge.net/
Также должно быть доступно в большинстве дистрибутивов. Вводное руководство здесь:
Некоторые перспективные инструменты:
nokogiri: парсинг HTML/XML DOM в ruby с использованием селекторов XPath и CSS
hpricot: устарел
fxgrep: использует собственный XPath-подобный синтаксис для запроса документов. Написано на SML, поэтому установка может быть затруднена.
LT XML: инструментарий XML, полученный из инструментов SGML, включая
sggrep
,sgsort
,xmlnorm
и другие. Использует собственный синтаксис запроса. Документация очень формальная. Написано на C. LT XML 2 заявляет о поддержке XPath, XInclude и других стандартов W3C.xmlgrep2: простой и мощный поиск с XPath. Написан на Perl с использованием XML::LibXML и libxml2.
XQSharp: поддерживает XQuery, расширение для XPath. Написано для.NET Framework.
xml-coreutils: набор инструментов Лейрда Брейера, эквивалентный GNU coreutils. Обсуждается интересное эссе о том, что должен включать в себя идеальный инструментарий.
xmldiff: простой инструмент для сравнения двух XML-файлов.
xmltk: похоже, не имеет пакетов в Debian, Ubuntu, Fedora или MacPort, не выпускал с 2007 года и использует непереносимую автоматизацию сборки.
xml-coreutils кажется наиболее документированным и наиболее ориентированным на UNIX.
Существует также xml2
а также 2xml
пара. Это позволит обычным инструментам редактирования строк обрабатывать XML.
Пример. q.xml:
<?xml version="1.0"?>
<foo>
text
more text
<textnode>ddd</textnode><textnode a="bv">dsss</textnode>
<![CDATA[ asfdasdsa <foo> sdfsdfdsf <bar> ]]>
</foo>
xml2 < q.xml
/foo=
/foo= text
/foo= more text
/foo=
/foo/textnode=ddd
/foo/textnode
/foo/textnode/@a=bv
/foo/textnode=dsss
/foo=
/foo= asfdasdsa <foo> sdfsdfdsf <bar>
/foo=
xml2 < q.xml | grep textnode | sed 's!/foo!/bar/baz!' | 2xml
<bar><baz><textnode>ddd</textnode><textnode a="bv">dsss</textnode></baz></bar>
PS Есть также html2
/ 2html
,
К превосходному списку Джозефа Холстена я добавляю скрипт командной строки xpath, который поставляется с библиотекой Perl XML::XPath. Отличный способ извлечь информацию из файлов XML:
xpath -q -e '/entry[@xml:lang="fr"]' *xml
Вы можете использовать xmllint:
xmllint --xpath //title books.xml
Должен быть в комплекте с большинством дистрибутивов, а также в комплекте с Cygwin.
$ xmllint --version
xmllint: using libxml version 20900
Увидеть:
$ xmllint
Usage : xmllint [options] XMLfiles ...
Parse the XML files and output the result of the parsing
--version : display the version of the XML library used
--debug : dump a debug tree of the in-memory document
...
--schematron schema : do validation against a schematron
--sax1: use the old SAX1 interfaces for processing
--sax: do not build a tree but work just at the SAX level
--oldxml10: use XML-1.0 parsing rules before the 5th edition
--xpath expr: evaluate the XPath expression, inply --noout
Если вы ищете решение для Windows, Powershell имеет встроенную функциональность для чтения и записи XML.
test.xml:
<root>
<one>I like applesauce</one>
<two>You sure bet I do!</two>
</root>
Скрипт Powershell:
# load XML file into local variable and cast as XML type.
$doc = [xml](Get-Content ./test.xml)
$doc.root.one #echoes "I like applesauce"
$doc.root.one = "Who doesn't like applesauce?" #replace inner text of <one> node
# create new node...
$newNode = $doc.CreateElement("three")
$newNode.set_InnerText("And don't you forget it!")
# ...and position it in the hierarchy
$doc.root.AppendChild($newNode)
# write results to disk
$doc.save("./testNew.xml")
testNew.xml:
<root>
<one>Who likes applesauce?</one>
<two>You sure bet I do!</two>
<three>And don't you forget it!</three>
</root>
Источник: https://serverfault.com/questions/26976/update-xml-from-the-command-line-windows
Также есть xmlsed & xmlgrep для NetBSD xmltools!
Зависит от того, что именно вы хотите сделать.
XSLT может быть способом пойти, но есть кривая обучения. Попробуйте xsltproc и обратите внимание, что вы можете передать параметры.
Д. Богдан поддерживает репозиторий GitHub с открытым исходным кодом, в котором хранится список инструментов командной строки для инструментов структурированного текста, есть раздел для инструментов XML/HTML:
Есть также saxon-lint
из командной строки с возможностью использования XPath 3.0/XQuery 3.0. (Другие инструменты командной строки используют XPath 1.0).
ПРИМЕРЫ:
HTTP / HTML:
$ saxon-lint --html --xpath 'count(//a)' http://stackru.com/q/91791
328
xml:
$ saxon-lint --xpath '//a[@class="x"]' file.xml
XQuery может быть хорошим решением. Его (относительно) легко изучить и он является стандартом W3C.
Я бы порекомендовал XQSharp для процессора командной строки.
Сначала я использовал xmlstarlet и до сих пор его использую. Когда запрос становится сложным, мне нужна поддержка функций XML xpath2 и xquery, я обращаюсь к xidel http://www.videlibri.de/xidel.html
Эквивалент Grep
Вы можете определить функцию bash, скажем "xp" ("xpath"), которая обертывает некоторый код python3. Чтобы использовать его, вам необходимо установить python3 и python-lxml. Льготы:
- регулярное выражение, которого вам не хватает, например, xmllint.
- Использовать как фильтр (в конвейере) в командной строке
Его легко и эффективно использовать вот так:
xmldoc=$(cat <<EOF
<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>
EOF
)
selection='//*[namespace-uri()="http://www.sample.com/" and local-name()="job" and re:test(.,"^pro.*ing$")]/text()'
echo "$xmldoc" | xp "$selection"
# prints programming
xp () выглядит примерно так:
xp()
{
local selection="$1";
local xmldoc;
if ! [[ -t 0 ]]; then
read -rd '' xmldoc;
else
xmldoc="$2";
fi;
python3 <(printf '%b' "from lxml.html import tostring\nfrom lxml import etree\nfrom sys import stdin\nregexpNS = \"http://exslt.org/regular-expressions\"\ntree = etree.parse(stdin)\nfor e in tree.xpath('""$selection""', namespaces={'re':regexpNS}):\n if isinstance(e, str):\n print(e)\n else:\n print(tostring(e).decode('UTF-8'))") <<< "$xmldoc"
}
Sed эквивалент
Рассмотрите возможность использования xq, который дает вам всю мощь "языка программирования" jq. Если у вас установлен python-pip, вы можете установить xq с помощью pip install yq, тогда в приведенном ниже примере мы заменяем "Сохранить учетные записи" на "Сохранить учетные записи 2":
xmldoc=$(cat <<'EOF'
<resources>
<string name="app_name">Keep Accounts</string>
<string name="login">"login"</string>
<string name="login_password">"password:"</string>
<string name="login_account_hint">input to login</string>
<string name="login_password_hint">input your password</string>
<string name="login_fail">login failed</string>
</resources>
EOF
)
echo "$xmldoc" | xq '.resources.string = ([.resources.string[]|select(."#text" == "Keep Accounts") ."#text" = "Keep Accounts 2"])' -x
Решите, какие операции вы хотите выполнять с файлами XML, и создайте сценарий (возможно, на Python, Perl), который предоставляет эту функциональность через аргументы для использования сценариями оболочки.
JEdit имеет плагин под названием "XQuery", который обеспечивает функциональность запросов для документов XML.
Не совсем командная строка, но она работает!