Created
August 26, 2020 17:40
-
-
Save flavorjones/8f29ab8cab491db39031047b923c76de to your computer and use it in GitHub Desktop.
Script to help with https://groups.google.com/g/nokogiri-talk/c/9ikl3vlfMO8/m/hu-o1jiSCQAJ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env ruby | |
require "nokogiri" | |
xml = <<EOF | |
<?xml version="1.0" encoding="UTF-8"?> | |
<kml xmlns="http://www.opengis.net/kml/2.2"> | |
<Document> | |
<name>Document.kml</name> | |
<Placemark> | |
<name>Waypoint</name> | |
<Point> | |
<coordinates>-122.371,37.816,0</coordinates> | |
</Point> | |
</Placemark> | |
<Placemark> | |
<name>Track</name> | |
<LineString> | |
<coordinates>-0.376291,43.296237,199.75 -0.376299,43.296237,199.75</coordinates> | |
</LineString> | |
</Placemark> | |
</Document> | |
</kml> | |
EOF | |
doc = Nokogiri::XML(xml) | |
# 1. insert/replace the document's name. | |
# | |
# First, let's find the name node. | |
# For explanation of why the "xmlns" is needed, check out: | |
# > https://nokogiri.org/tutorials/searching_a_xml_html_document.html#namespaces | |
# | |
name_node = doc.at_xpath("/xmlns:kml/xmlns:Document/xmlns:name") | |
# | |
# You could also use a CSS query which will (mostly) ignore namespaces. This is exactly the same search. | |
# | |
name_node = doc.at_css("kml > Document > name") | |
# | |
# Modify the contents of the <name/> node | |
# | |
name_node.content = "New Document Name" | |
# 2. a. find all Placemark blocks that contain a LineString | |
# | |
# I can think of two ways to do this. The first way is to search for | |
# LineString nodes within a Placemark node, and then get those nodes' parents: | |
placemarks_with_linestring = doc.xpath("//xmlns:Placemark/xmlns:LineString").map(&:parent) | |
# This first approach would work with CSS as well: | |
placemarks_with_linestring = doc.css("Placemark > LineString").map(&:parent) | |
# The second approach is to just use an XPath query to express that | |
# you want Placemarks that contain a LineString: | |
placemarks_with_linestring = doc.xpath("//xmlns:Placemark[xmlns:LineString]") | |
# Then you can add a new child node to that Placemark: | |
placemarks_with_linestring.each do |placemark| | |
# the string passed into add_child is parsed just like any other XML fragment | |
placemark.add_child "<some>blah</some>" | |
end | |
# The end result: | |
puts doc.to_xml | |
# >> <?xml version="1.0" encoding="UTF-8"?> | |
# >> <kml xmlns="http://www.opengis.net/kml/2.2"> | |
# >> <Document> | |
# >> <name>New Document Name</name> | |
# >> <Placemark> | |
# >> <name>Waypoint</name> | |
# >> <Point> | |
# >> <coordinates>-122.371,37.816,0</coordinates> | |
# >> </Point> | |
# >> </Placemark> | |
# >> <Placemark> | |
# >> <name>Track</name> | |
# >> <LineString> | |
# >> <coordinates>-0.376291,43.296237,199.75 -0.376299,43.296237,199.75</coordinates> | |
# >> </LineString> | |
# >> <some>blah</some></Placemark> | |
# >> </Document> | |
# >> </kml> | |
# 3. Write this to a file | |
# | |
# Use normal Ruby idioms for opening a file and writing to it, and use #to_xml to serialize the doc: | |
File.open("output.kml", "w") do |file| | |
file.write doc.to_xml | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment