Удаление элементов из KML (Python)

#python #xml #automation #gis #kml

#python #xml #автоматизация #гис #kml

Вопрос:

Я сгенерировал файл KML, используя библиотеку SimpleKML на Python и следующий скрипт, вывод которого также показан ниже:

 import simplekml
kml = simplekml.Kml()
ground = kml.newgroundoverlay(name='Aerial Extent')
ground.icon.href = 'C:\Users\mdl518\Desktop\aerial_image.png'
ground.latlonbox.north = 46.55537
ground.latlonbox.south = 46.53134
ground.latlonbox.east = 48.60005
ground.latlonbox.west = 48.57678
ground.latlonbox.rotation = 0.090320 
kml.save(".//aerial_extent.kml")
 

Вывод KML:

 <?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
    <Document id="1">
        <GroundOverlay id="2">
            <name>Aerial Extent</name>
            <Icon id="3">
                <href>C:\Users\mdl518\Desktop\aerial_image.png</href>
            </Icon>
            <LatLonBox>
                <north>46.55537</north>
                <south>46.53134</south>
                <east>48.60005</east>
                <west>48.57678</west>
                <rotation>0.090320</rotation>
        </LatLonBox>
    </GroundOverlay>
</Document>
 

Тем не менее, я пытаюсь удалить тег «Document» из этого KML, поскольку он является элементом по умолчанию, созданным с помощью SimpleKML, сохраняя при этом дочерние элементы (например, GroundOverlay). Кроме того, есть ли способ удалить атрибуты «id», связанные с определенными элементами (например, для GroundOverlay, элементов Icon)? Я изучаю использование ElementTree / lxml, чтобы включить это, но они, похоже, более специфичны для файлов XML, в отличие от KML. Вот что я пытаюсь использовать для изменения KML, но он не может удалить элемент Document:

 from lxml import etree
tree = etree.fromstring(open("C:\Users\mdl518\Desktop\aerial_extent.kml").read())
for item in tree.xpath("//Document[@id='1']"):
    item.getparent().remove(item)

print(etree.tostring(tree, pretty_print=True))
 

Вот конечный желаемый выходной XML:

 <?xml version="1.0" encoding="UTF-8"?>

<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
    <GroundOverlay>
         <name>Aerial Extent</name>
         <Icon>
             <href>C:\Users\mdl518\Desktop\aerial_image.png</href>
         </Icon>
         <LatLonBox>
              <north>46.55537</north>
              <south>46.53134</south>
              <east>48.60005</east>
              <west>48.57678</west>
              <rotation>0.090320</rotation>
         </LatLonBox>
    </GroundOverlay>
</kml>
 

Любые идеи приветствуются!

Комментарии:

1. Файлы KML также являются XML, поэтому lxml — прекрасный способ манипулировать ими. Будет ли он по-прежнему действительным KML после ваших изменений, это, конечно, зависит от вас 🙂

2. @Thomas — Я понимаю, что KML-файлы по сути являются XML-файлами, но я просто наблюдал за тем, что казалось чувствительным к расширениям файлов, используя библиотеки lxml / ElementTree. Я обновил свой пост, показывающий скрипт, который я пытаюсь использовать для удаления тега Document, любая помощь приветствуется!

Ответ №1:

Вы сталкиваетесь с ужасными пространствами имен…

Попробуйте использовать что-то вроде этого:

 ns = {'kml': 'http://www.opengis.net/kml/2.2'}
for item in tree.xpath("//kml:Document[@id='1']",namespaces=ns):
    item.getparent().remove(item)
 

Редактировать:

Чтобы удалить только родительский элемент и сохранить все его потомки, попробуйте выполнить следующие действия:

 retain = doc.xpath("//kml:Document[@id='1']/kml:GroundOverlay",namespaces=ns)[0]
for item in doc.xpath("//kml:Document[@id='1']",namespaces=ns):
    anchor = item.getparent()
    anchor.remove(item)
    anchor.insert(1,retain)

print(etree.tostring(doc, pretty_print=True).decode())
 

Это должно дать вам желаемый результат.

Комментарии:

1. Это помогает указать мне правильное направление, но выполнение этого скрипта удаляет все дочерние элементы ниже элемента «Document». Я буду продолжать подключаться к этому, поскольку для получения правильного решения должно быть всего несколько настроек, еще раз спасибо!

2. @mdl518 Ну, это то, что вы сказали в своем вопросе — вы хотели удалить <Document> элемент; это включает в себя все, что внутри него. Если это не то, что вам нужно, вам, вероятно, следует опубликовать другой вопрос с другим xml и желаемым результатом.

3. Приношу свои извинения за любую двусмысленность, но да, идея состоит в том, чтобы удалить элемент Document, сохранив дочерние элементы (например, GroundOverlay). Теперь это отражено в обновленном сообщении.

4. @mdl518 Теперь я понимаю, но вам, вероятно, следует снова отредактировать свой вопрос и показать точный ожидаемый результат.

5. Спасибо за ваш полезный отзыв, теперь это добавлено к исходному сообщению … очень ценится!