删除包含特定元素的 XML 节点

Ter*_*ior 4 xml sed python perl regular-expression

我想从包含元素的 KML 文件中删除所有地标<tessellate>。应完全删除以下块:

<Placemark>
    <styleUrl>#m_ylw-pushpin330</styleUrl>
    <LineString>
        <tessellate>1</tessellate>
        <coordinates>
            0.0000000000000,0.0000000000000,0 0.0000000000000,0.0000000000000,0
        </coordinates>
    </LineString>
</Placemark>
Run Code Online (Sandbox Code Playgroud)

我尝试了一些非贪婪的 perl 正则表达式,但没有运气(很多东西与第一个一起删除<Placemark>):

sed -r ':a; N; $!ba; s/\n\t*//g' myplaces.kml |
perl -pe 's|<Placemark>.*?<tessellate>.*?</Placemark>||g'
Run Code Online (Sandbox Code Playgroud)

我相信 XML 解析器是可行的方法,但我阅读了 xmlstarlet 的文档却一无所获。所以也欢迎xmlstarlet、python等任何解决方案!

Sté*_*las 8

xmlstarlet

xmlstarlet ed -d '//Placemark[.//tessellate]' < myplaces.kml
Run Code Online (Sandbox Code Playgroud)

kml使用命名空间时,您必须先定义它(请参阅 xmlstarlet 文档

xmlstarlet ed -N 'ns=http://www.opengis.net/kml/2.2' -d '//ns:Placemark[.//ns:tessellate]'
Run Code Online (Sandbox Code Playgroud)

使用perl,您需要将文件作为一个整体(而不是逐行)处理并将s标志添加到s///. 即便如此,即使使用非贪婪匹配,它仍然会从第一个<Placemark>开始匹配next</Placemark>之后发生的下一个<tessellate>。所以你需要这样写:

perl -0777 -pe 's|(<Placemark>.*?</Placemark>)|
   $1 =~ /<tessellate>/?"":$1|gse'
Run Code Online (Sandbox Code Playgroud)