在编写 shell 脚本时,通常数据将位于单行记录文件中,例如 csv。grep
使用和处理这些数据非常简单sed
。但是我必须经常处理 XML,所以我真的想要一种通过命令行对 XML 数据进行脚本访问的方法。什么是最好的工具?
14 回答
一些有前途的工具:
nokogiri:使用 XPath 和 CSS 选择器在 ruby 中解析 HTML/XML DOM
hpricot:已弃用
fxgrep:使用自己的类似 XPath 的语法来查询文档。用 SML 编写,因此安装可能很困难。
LT XML:派生自 SGML 工具的 XML 工具包,包括
sggrep
、sgsort
等xmlnorm
。使用自己的查询语法。文档 非常正式。用 C 语言编写。LT XML 2 声称支持 XPath、XInclude 和其他 W3C 标准。xmlgrep2:使用 XPath 进行简单而强大的搜索。使用 XML::LibXML 和 libxml2 用 Perl 编写。
XQSharp:支持 XQuery,XPath 的扩展。为 .NET 框架编写。
xml-coreutils:Laird Breyer 的工具包,相当于 GNU coreutils。在一篇有趣的文章中讨论了理想的工具包应该包括什么。
xmldiff:用于比较两个 xml 文件的简单工具。
xmltk:在 debian、ubuntu、fedora 或 macports 中似乎没有包,自 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
。
在 Joseph Holsten 的优秀列表中,我添加了 Perl 库 XML::XPath 附带的 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 的内置功能。
测试.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
还有 NetBSD xmltools 的 xmlsed 和 xmlgrep!
完全取决于你想做什么。
XSLT 可能是要走的路,但有一个学习曲线。试试xsltproc,注意可以交参数。
saxon-lint
命令行也可以使用 XPath 3.0/XQuery 3.0。(其他命令行工具使用 XPath 1.0)。
例子 :
http/html:
$ saxon-lint --html --xpath 'count(//a)' http://stackoverflow.com/q/91791
328
xml:
$ saxon-lint --xpath '//a[@class="x"]' file.xml
D. Bohdan 维护一个开源 GitHub 存储库,其中包含用于结构化文本工具的命令行工具列表,其中有一个用于 XML/HTML 工具的部分:
XQuery 可能是一个很好的解决方案。它(相对)容易学习并且是 W3C 标准。
我会推荐XQSharp作为命令行处理器。
我第一次使用xmlstarlet并且仍在使用它。当查询变得困难时,我需要 XML 的xpath2和xquery功能支持我转向xidel http://www.videlibri.de/xidel.html
Grep 等价物
您可以定义一个 bash 函数,比如包装一些 python3 代码的“xp”(“xpath”)。要使用它,您需要安装 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,您可以使用 pip install yq安装 xq ,然后在下面的示例中,我们将“Keep Accounts”替换为“Keep Accounts 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
JEdit 有一个名为“XQuery”的插件,它为 XML 文档提供查询功能。
不完全是命令行,但它可以工作!