要素<tessellate>
を含むKMLファイルからすべての目印を削除したい。次のブロックはwhollyを削除する必要があります。
<Placemark>
<styleUrl>#m_ylw-pushpin330</styleUrl>
<LineString>
<tessellate>1</tessellate>
<coordinates>
0.0000000000000,0.0000000000000,0 0.0000000000000,0.0000000000000,0
</coordinates>
</LineString>
</Placemark>
私は運が悪かったいくつかの貪欲でないPerl正規表現を試しました(最初の<Placemark>
と一緒に多くのものが削除されます):
sed -r ':a; N; $!ba; s/\n\t*//g' myplaces.kml |
Perl -pe 's|<Placemark>.*?<tessellate>.*?</Placemark>||g'
私はXMLパーサーを使用する方法だと思いますが、xmlstarletのドキュメントを読んでどこにも行きませんでした。したがって、xmlstarlet、pythonなどのソリューションも歓迎します!
xmlstarlet
の場合:
xmlstarlet ed -d '//Placemark[.//tessellate]' < myplaces.kml
また、kml
は名前空間を使用するため、最初に名前空間を定義する必要があります( xmlstarletのドキュメント を参照)。
xmlstarlet ed -N 'ns=http://www.opengis.net/kml/2.2' -d '//ns:Placemark[.//ns:tessellate]'
Perl
を使用する場合は、ファイル全体を(1行ずつではなく)処理し、s
フラグをs///
に追加する必要があります。そしてそれでも、貪欲でない一致があっても、最初の<Placemark>
から次の</Placemark>
まで、次の<tessellate>
の後に発生します。したがって、次のように記述する必要があります。
Perl -0777 -pe 's|(<Placemark>.*?</Placemark>)|
$1 =~ /<tessellate>/?"":$1|gse'
このテストファイルを考えると:
start
<Placemark>
<tessellate>1</tessellate>
</Placemark>
middle1
<Placemark>
</Placemark>
middle2
<Placemark>
<tessellate>1</tessellate>
</Placemark>
end
もしあなたがそうするなら Perl -0 -pe 's|<Placemark>.*?<tessellate>.*?</Placemark>||gs'
あなたが提案したように、それはあまりにも多くを取り除くでしょう:
start
middle1
end
これは、正規表現が楽しみにしているだけだからです。開始タグを検出し、最初のテッセレートタグまで、次の終了タグまですべてを取得します。残念ながら、それが途中でより多くの開始タグを消費するかどうかは気にしません...
正規表現でそれをしたい場合は、各ブロックを独自に処理する必要があります:Perl -0 -pe 's|<Placemark>.*?</Placemark>|$&=~/<tessellate>/?"":$&|gse'
これにより、望ましい結果が得られるはずです。
標準モジュールでPython(2.7)を使用する:
ファイルtest.xml
:
<Container>
<Placemark>
<KeepMe/>
</Placemark>
<Placemark>
<styleUrl>#m_ylw-pushpin330</styleUrl>
<LineString>
<tessellate>1</tessellate>
<coordinates>
0.0000000000000,0.0000000000000,0 0.0000000000000,0.0000000000000,0
</coordinates>
</LineString>
</Placemark>
</Container>
そしてプログラム:
#! /usr/bin/env python
from __future__ import print_function # works on 2.x and 3.x
from lxml import etree
file_name = 'test.xml'
root = etree.parse(file_name)
for element in root.iterfind('.//Placemark'):
if(element.find('.//tessellate')) is not None:
element.getparent().remove(element)
print(etree.tostring(root))
出力として与える:
<Container>
<Placemark>
<KeepMe/>
</Placemark>
</Container>