Created
March 5, 2022 15:36
-
-
Save dmd/823add215b1af43c5663b7bc52d02f11 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
# Photos - XML metadata to printable | |
1. Read the XML file | |
2. Drop fields, reformat GPS | |
Transform: | |
``` | |
out :: reformat(in) = | |
begin | |
let clat = in.RDF.Description.Composite_GPSLatitude; // 40 deg 40' 27.16" N | |
let clon = in.RDF.Description.Composite_GPSLongitude; // 73 deg 55' 50.80" W | |
let clatDMSF = re_split(clat, '\\D+')[0:4]; | |
let clonDMSF = re_split(clon, '\\D+')[0:4]; | |
let lat_deg = (float)(decimal(''))clatDMSF[0]; | |
let lat_min = (float)(decimal(''))clatDMSF[1]; | |
let lat_sec = (float)(decimal(''))clatDMSF[2]; | |
let lat_fra = (float)(decimal(''))clatDMSF[3]; | |
let lon_deg = (float)(decimal(''))clonDMSF[0]; | |
let lon_min = (float)(decimal(''))clonDMSF[1]; | |
let lon_sec = (float)(decimal(''))clonDMSF[2]; | |
let lon_fra = (float)(decimal(''))clatDMSF[3]; | |
let lat_sign = if (is_defined(re_get_match(clat, '[swSW]'))) -1 else 1; | |
let lon_sign = if (is_defined(re_get_match(clon, '[swSW]'))) -1 else 1; | |
let lat = lat_sign * (lat_deg + lat_min / 60 + lat_sec / 3600 + lat_fra / 36000); | |
let lon = lon_sign * (lon_deg + lon_min / 60 + lon_sec / 3600 + lon_fra / 36000); | |
out.FileName :: in.RDF.Description.FileName; | |
out.DateTimeOriginal :: first_defined(in.RDF.Description.DateTimeOriginal,in.RDF.Description.DateTimeCreated); | |
out.Description :: first_defined(in.RDF.Description.Description,in.RDF.Description.ImageDescription, ''); | |
out.Title:: if (is_null(in.RDF.Description.Title) or in.RDF.Description.Title == 'Untitled' ) '' else in.RDF.Description.Title; | |
out.Keywords:: vector_sort_dedup_first(in.RDF.Description.Keywords.Bag.li); | |
out.ImageSize :: in.RDF.Description.ImageSize; | |
out.GPSPosition :: in.RDF.Description.GPSPosition; | |
out.GPSLatitudeDecimal :: first_defined(lat, '0'); | |
out.GPSLongitudeDecimal :: first_defined(lon, '0'); | |
end; | |
``` | |
Output DML: | |
``` | |
record | |
string('') FileName; | |
datetime('YYYY:MM:DD HH24:MI:SS') DateTimeOriginal; | |
utf8 string('') Description = NULL; | |
utf8 string('') Title = NULL; | |
utf8 string('')[int] Keywords = NULL; | |
string('') ImageSize; | |
string('') GPSPosition = NULL; | |
decimal('') GPSLatitudeDecimal; | |
decimal('') GPSLongitudeDecimal; | |
end; | |
``` | |
3. Enrich location | |
``` | |
constant string('') GOOGLE_GEO_API_KEY parameter; // AIzaSyDtYAOwrl8hpVm43H3lcJpMRn6gJL8L6Fg | |
constant string('') GOOGLE_GEO_URL parameter; // https://maps.googleapis.com/maps/api/geocode/xml | |
request :: prepare_request(in) = | |
begin | |
request.request_url :: GOOGLE_GEO_URL; | |
request.request_url_params :: [vector [record name "latlng" value string_concat(in.GPSLatitudeDecimal, ',', in.GPSLongitudeDecimal)], [record name "key" value GOOGLE_GEO_API_KEY]]; | |
end; | |
out :: create_output(in, responses) = | |
begin | |
out.FileName :: in.FileName; | |
out.response_body::reinterpret(responses.response_body); | |
end; | |
``` | |
4. Parse the geoxml | |
DML: | |
``` | |
type xml_doc_t = utf8 record | |
decimal('') seq_num; | |
string('')[big endian integer(4)] formatted_address; | |
string('',charset="x-ab-internal") XML_fields() = 'seq_num=seqnum(),=GeocodeResponse/%e/status,=GeocodeResponse/%e/result{1-n}/%e/type{1-n},formatted_address=GeocodeResponse/%e/result{1-n}/%e/formatted_address/text(),=GeocodeResponse/%e/result{1-n}/%e/address_component{1-n},=GeocodeResponse/%e/result{1-n}/%e/geometry,=GeocodeResponse/%e/result{1-n}/%e/place_id'; | |
string('',charset="x-ab-internal") XML_generated_by_version() = '3.2.6.0'; | |
string('',charset="x-ab-internal") XML_generated_at_compatibility() = ''; | |
end; | |
metadata type = record | |
string('') FileName; | |
string('') DateTimeOriginal; | |
utf8 string('') Description = NULL; | |
utf8 string('') Title = NULL; | |
utf8 string('')[big endian integer(4)] Keywords = NULL; | |
string('') ImageSize; | |
string('') GPSPosition = NULL; | |
decimal('') GPSLatitudeDecimal; | |
decimal('') GPSLongitudeDecimal; | |
xml_doc_t geo; | |
end; | |
``` | |
5. Reformat for text output | |
Transform: | |
``` | |
out :: reformat(in) = | |
begin | |
out.* :: in.*; | |
out.GPSCoords :: (string(''))in.GPSLatitudeDecimal + ',' + (string(''))in.GPSLongitudeDecimal; | |
out.Place :: string_join(in.geo.formatted_address[0:3], '\n'); | |
out.Keywords :: string_join(in.Keywords, ', '); | |
out.FileName :: string_replace(in.FileName,'.jpg',''); | |
end; | |
``` | |
Final output DML: | |
``` | |
record | |
string(6) lab_start_rec = '===== '; | |
string(' ') FileName; | |
string('\n') lab_start_rec_e = '====='; | |
string(6) lab_date = 'Date: '; | |
string('\n') DateTimeOriginal; | |
string(7) lab_title = 'Title: '; | |
utf8 string('\n') Title = NULL; | |
string(10) lab_desc = 'Desc\n----\n'; | |
utf8 string('\n\n') Description = NULL; | |
string(10) lab_keywords = 'Keywords: '; | |
utf8 string('\n') Keywords = NULL; | |
string(6) lab_size = 'Size: '; | |
string('\n') ImageSize; | |
string(5) lab_gps = 'GPS: '; | |
string('\n') GPSCoords; | |
string(14) lab_place = 'Places\n------\n'; | |
utf8 string('\n\n\n') Place; | |
//string(2) end_rec = '\n\n'; | |
end; | |
``` | |
Done! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment