특정 요소가 포함된 XML 노드 삭제

특정 요소가 포함된 XML 노드 삭제

이 요소가 포함된 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>

나는 탐욕스럽지 않은 Perl 정규식을 시도했지만 성공하지 못했습니다(많은 것들이 첫 번째 것과 함께 제거되었습니다 <Placemark>).

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

나는 XML 파서가 갈 길이라고 생각하지만 xmlstarlet에 대한 문서를 읽었지만 아무것도 찾지 못했습니다. 따라서 xmlstarlet, python 등의 솔루션도 환영합니다!

답변1

그리고 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파일을 한 줄씩 처리하지 않고 전체적으로 처리하고 s에 플래그를 추가해야 합니다 s///. 그럼에도 불구하고 비 욕심적 일치를 사용하더라도 첫 번째 항목부터 다음 항목까지 일치합니다. 다음 것 <Placemark>. 따라서 다음과 같이 작성해야 합니다.</Placemark><tessellate>

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

답변2

이 테스트 파일이 주어지면:

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'

이렇게 하면 원하는 결과를 얻을 수 있습니다.

답변3

표준 모듈과 함께 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>

관련 정보