您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
geoKMLer is a JavaScript library designed to convert KML data into GeoJSON format efficiently. It supports conversion of Placemarks containing Point, LineString, Polygon, and MultiGeometry elements.
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greasyfork.icu/scripts/524747/1528426/GeoKMLer.js
// ==UserScript== // @name GeoKMLer // @namespace https://github.com/JS55CT // @description geoKMLer is a JavaScript library designed to convert KML data into GeoJSON format efficiently. It supports conversion of Placemarks containing Point, LineString, Polygon, and MultiGeometry elements. // @version 2.0.0 // @author JS55CT // @license GNU GPLv3 // @match *://this-library-is-not-supposed-to-run.com/* // ==/UserScript== /*********************************************************** * ## Project Home < https://github.com/JS55CT/GeoKMLer > * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * **************************************************************/ var GeoKMLer = (function() { /** * GeoKMLer constructor function. * @param {Object} obj - Optional object to wrap. * @returns {GeoKMLer} - An instance of GeoKMLer. */ function GeoKMLer(obj) { if (obj instanceof GeoKMLer) return obj; if (!(this instanceof GeoKMLer)) return new GeoKMLer(obj); this._wrapped = obj; } /** * Parses a KML string into an XML DOM. * @param {string} kmlText - The KML text to parse. * @returns {Document} - The parsed XML document. */ GeoKMLer.prototype.read = function(kmlText) { const document = new DOMParser().parseFromString(kmlText, "application/xml"); return document; }; /** * Converts a KML document to a GeoJSON FeatureCollection. * @param {Document} document - The KML document to convert. * @returns {Object} - The resulting GeoJSON FeatureCollection. */ GeoKMLer.prototype.toGeoJSON = function(document) { const features = []; for (const placemark of document.getElementsByTagName("Placemark")) { features.push(...this.handlePlacemark(placemark)); } return { type: "FeatureCollection", features: features }; }; /** * Processes a KML Placemark and converts its geometries to GeoJSON features. * @param {Element} placemark - The Placemark element to process. * @returns {Array} - An array of GeoJSON features. */ GeoKMLer.prototype.handlePlacemark = function(placemark) { const features = []; const properties = this.extractProperties(placemark); // Merge extended data directly into the properties without an additional 'ExtendedData' entry Object.assign(properties, this.extractExtendedData(placemark)); for (let i = 0; i < placemark.children.length; i++) { const element = placemark.children[i]; switch (element.tagName) { case "Point": features.push(this.pointToPoint(element, placemark, properties)); break; case "LineString": features.push(this.lineStringToLineString(element, placemark, properties)); break; case "Polygon": features.push(this.polygonToPolygon(element, placemark, properties)); break; case "MultiGeometry": features.push(...this.handleMultiGeometry(element, placemark, properties)); break; } } return features; }; /** * Converts coordinate strings into arrays of [longitude, latitude]. * @param {string} coordString - The coordinate string from KML. * @returns {Array} - An array of [longitude, latitude] pairs. */ GeoKMLer.prototype.coordFromString = function(coordString) { return coordString.trim().split(/\s+/).map(coord => { const [lon, lat] = coord.split(',').map(parseFloat); return [lon, lat]; }); }; /** * Parses a single coordinate string into a numeric array. * @param {string} v - The coordinate string. * @returns {Array} - An array of parsed coordinate values. */ GeoKMLer.prototype.coord1 = function(v) { const removeSpace = /\s*/g; return v.replace(removeSpace, '').split(',').map(parseFloat); }; /** * Parses multiple coordinate strings into an array of coordinate arrays. * @param {string} v - The coordinate string with multiple coordinates. * @returns {Array} - A nested array of parsed coordinate values. */ GeoKMLer.prototype.coord = function(v) { const trimSpace = /^\s*|\s*$/g; const splitSpace = /\s+/; const coords = v.replace(trimSpace, '').split(splitSpace); return coords.map(coord => this.coord1(coord)); }; /** * Extracts extended data from a KML placemark. * @param {Element} placemark - The Placemark element to extract from. * @returns {Object} - An object containing extended data properties. */ GeoKMLer.prototype.extractExtendedData = function(placemark) { const extendedData = {}; const extendedDataTag = this.getChildNode(placemark, 'ExtendedData'); if (!extendedDataTag) return extendedData; const simpleDatas = this.getChildNodes(extendedDataTag, 'SimpleData'); simpleDatas.forEach(data => { const name = data.getAttribute('name'); const value = this.nodeVal(data); if (name && value !== null) { extendedData[`ex_${name}`] = value.trim(); } }); return extendedData; }; /** * Fetches the value of a text node. * @param {Node} x - The node to extract the value from. * @returns {string} - The text content of the node. */ GeoKMLer.prototype.nodeVal = function(x) { return x ? x.textContent || '' : ''; }; /** * Retrieves a single child node of a specified tag name. * @param {Element} x - The parent element. * @param {string} y - The tag name of the child node. * @returns {Element|null} - The first matching child node or null if none are found. */ GeoKMLer.prototype.getChildNode = function(x, y) { const nodeList = x.getElementsByTagName(y); return nodeList.length ? nodeList[0] : null; }; /** * Retrieves all child nodes of a specified tag name. * @param {Element} x - The parent element. * @param {string} y - The tag name of the child nodes. * @returns {Array} - An array of matching child nodes. */ GeoKMLer.prototype.getChildNodes = function(x, y) { return Array.from(x.getElementsByTagName(y)); }; /** * Retrieves an attribute value from an element. * @param {Element} x - The element to extract the attribute from. * @param {string} y - The name of the attribute. * @returns {string|null} - The attribute value or null if not present. */ GeoKMLer.prototype.attr = function(x, y) { return x.getAttribute(y); }; /** * Retrieves a floating-point attribute value from an element. * @param {Element} x - The element to extract the attribute from. * @param {string} y - The name of the attribute. * @returns {number} - The parsed floating-point attribute value. */ GeoKMLer.prototype.attrf = function(x, y) { return parseFloat(this.attr(x, y)); }; /** * Normalizes an XML node to combine adjacent text nodes. * @param {Node} el - The XML node to normalize. * @returns {Node} - The normalized node. */ GeoKMLer.prototype.norm = function(el) { if (el.normalize) el.normalize(); return el; }; /** * Creates a GeoJSON feature for a given geometry type and coordinates. * @param {string} type - The geometry type (Point, LineString, Polygon). * @param {Array} coords - The coordinates for the geometry. * @param {Object} props - The properties of the feature. * @returns {Object} - The created GeoJSON feature. */ GeoKMLer.prototype.makeFeature = function(type, coords, props) { return { type: "Feature", geometry: { type: type, coordinates: coords }, properties: props }; }; /** * Converts a KML Point to a GeoJSON Point feature. * @param {Element} node - The Point element. * @param {Element} placemark - The parent Placemark element. * @param {Object} props - The properties of the feature. * @returns {Object} - A GeoJSON Point feature. */ GeoKMLer.prototype.pointToPoint = function(node, placemark, props) { const coord = this.coordFromString(node.getElementsByTagName('coordinates')[0].textContent)[0]; return this.makeFeature("Point", coord, props); }; /** * Converts a KML LineString to a GeoJSON LineString feature. * @param {Element} node - The LineString element. * @param {Element} placemark - The parent Placemark element. * @param {Object} props - The properties of the feature. * @returns {Object} - A GeoJSON LineString feature. */ GeoKMLer.prototype.lineStringToLineString = function(node, placemark, props) { const coords = this.coordFromString(node.getElementsByTagName('coordinates')[0].textContent); return this.makeFeature("LineString", coords, props); }; /** * Converts a KML Polygon to a GeoJSON Polygon feature. * @param {Element} node - The Polygon element. * @param {Element} placemark - The parent Placemark element. * @param {Object} props - The properties of the feature. * @returns {Object} - A GeoJSON Polygon feature. */ GeoKMLer.prototype.polygonToPolygon = function(node, placemark, props) { const coords = []; for (const boundary of node.getElementsByTagName('LinearRing')) { coords.push(this.coordFromString(boundary.getElementsByTagName('coordinates')[0].textContent)); } return this.makeFeature("Polygon", coords, props); }; /** * Processes a MultiGeometry and converts its geometries to GeoJSON features. * @param {Element} node - The MultiGeometry element. * @param {Element} placemark - The parent Placemark element. * @param {Object} props - The properties of the features. * @returns {Array} - An array of GeoJSON features. */ GeoKMLer.prototype.handleMultiGeometry = function(node, placemark, props) { const features = []; for (const element of node.children) { switch (element.tagName) { case "Point": features.push(this.pointToPoint(element, placemark, props)); break; case "LineString": features.push(this.lineStringToLineString(element, placemark, props)); break; case "Polygon": features.push(this.polygonToPolygon(element, placemark, props)); break; case "MultiGeometry": features.push(...this.handleMultiGeometry(element, placemark, props)); break; } } return features; }; /** * Extracts properties from a Placemark, excluding geometry elements. * @param {Element} placemark - The Placemark element to extract properties from. * @returns {Object} - An object containing placemark properties. */ GeoKMLer.prototype.extractProperties = function(placemark) { const props = {}; for (const n of placemark.children) { if (!["Point", "LineString", "Polygon", "MultiGeometry", "LinearRing", "style", "styleMap", "styleUrl", "TimeSpan", "TimeStamp"].includes(n.tagName)) { // Ensure "ExtendedData" is not added directly. if (n.tagName !== "ExtendedData") { props[n.tagName] = n.textContent.trim(); } } } return props; }; return GeoKMLer; })();