xmllint_特定の文字列を持つノードの親ノードを取る方法
シェルでXMLの中身を使う機会があった。 ググれば基本的な使い方は出てくるけど、とあるテキストを含むノードと並んだノード、 つまり親ノードに登って違う子ノードを取りたい(分かりにくい)といった例がなかったのでメモ。
使用するコマンドはxmllint。Linuxでインストールすべきはlibxml2-utils。
(ubuntuの例:sudo apt install libxml2-utils
)
XPathで指定して情報を持ってこれる。 基本的なところは、xmllintとxpathでググって把握できると思われる。
でも、座標を含む要素なんかでありがちな、<要素>以下に座標があったり、 親子構造になっていて<要素><要素>以下に座標があったり。 これらの座標全部取りたい…となると、すぐは分からなかった。
例えばこんなXMLだったとする。
$ cat a.xml <?xml version="1.0"?> <asdf> <youso> <abc>text1</abc> <zahyo> <x>111</x> <y>222</y> </zahyo> </youso> <youso> <abc>tigauText</abc> <zahyo> <x>555</x> <y>666</y> </zahyo> <youso> <abc>text1</abc> <zahyo> <x>333</x> <y>444</y> </zahyo> </youso> </youso> </asdf>
階層関係なく、text1を含んで、並んで記載されたzahyoを取りたい。 でも違うテキストを含む(ここではtigauText)要素のzahyoはいらない。 そんなときのシェル例はこちら。
$ xmllint --xpath '//abc[text()="text1"]/parent::node()/zahyo/x' a.xml <x>111</x><x>333</x>
先頭の//abc で、全ての
あとは 【Shell】XMLファイルから要素や属性を抽出する - 発熱するマイナー魂 を参考にして整形すると、こんな感じ。
$ xmllint --xpath '//abc[text()="text1"]/parent::node()/zahyo/x' a.xml | ¥ sed -e "s/<\/x>/<\/x>\n/g" | sed -e "s/<x>\(.*\)<\/x>/\1/" 111 333
同じようにyも取って、配列に入れ込んでx,yを参照すれば、ほしい座標郡が取れそう。
$ xmllint --xpath '//abc[text()="text1"]/parent::node()/zahyo/y' a.xml | ¥ sed -e "s/<\/y>/<\/y>\n/g" | sed -e "s/<y>\(.*\)<\/y>/\1/" 222 444
(情報抜け(xはあるけどyが無い)は未考慮なのでご注意を)
参考文献
さいごに
- もし誰かの役にたったのなら…
ぜひ私のほしいものリストから
をお送りください…(´;ω;`)
シェルプログラミング実用テクニック (Software Design plus)
- 作者: 上田隆一,USP研究所
- 出版社/メーカー: 技術評論社
- 発売日: 2015/05/15
- メディア: 大型本
- この商品を含むブログ (8件) を見る
- もし誰かの役にたったのなら…
ぜひ私のほしいものリストから