Работа с XML в веб-картографии чаще всего связана с обменом геоданными в форматах KML, GPX и GeoRSS, а также с обработкой произвольных XML-структур, содержащих координаты объектов. Несмотря на доминирование GeoJSON в экосистеме современных картографических библиотек, XML остаётся распространённым форматом в GIS-системах и внешних API.
Leaflet не имеет встроенного полноценного парсера XML-форматов геоданных, однако предоставляет устойчивую архитектуру для интеграции через преобразование данных в GeoJSON или прямое создание слоёв на основе разобранного XML-документа.
Получение XML-документа в JavaScript обычно выполняется через
fetch или XMLHttpRequest. Современный подход
опирается на fetch с последующим преобразованием текста в
XML-структуру.
fetch('data/points.xml')
.then(response => response.text())
.then(str => {
const parser = new DOMParser();
const xml = parser.parseFromString(str, 'application/xml');
console.log(xml);
});
В результате получается DOM-дерево, с которым можно работать через стандартные методы:
getElementsByTagNamequerySelectorgetAttributeТипичный XML-файл с геоданными содержит элементы, описывающие точки, линии или полигоны. Пример структуры:
<markers>
<marker>
<name>Точка A</name>
<lat>51.1694</lat>
<lng>71.4491</lng>
</marker>
<marker>
<name>Точка B</name>
<lat>51.1280</lat>
<lng>71.4300</lng>
</marker>
</markers>
Обработка таких данных:
const markers = xml.getElementsByTagName('marker');
for (let i = 0; i < markers.length; i++) {
const el = markers[i];
const name = el.getElementsByTagName('name')[0].textContent;
const lat = parseFloat(el.getElementsByTagName('lat')[0].textContent);
const lng = parseFloat(el.getElementsByTagName('lng')[0].textContent);
L.marker([lat, lng])
.addTo(map)
.bindPopup(name);
}
Ключевым моментом является преобразование строковых значений координат в числовой формат.
Наиболее устойчивый подход к интеграции XML с Leaflet заключается в
преобразовании данных в GeoJSON и использовании
L.geoJSON.
function xmlToGeoJSON(xml) {
const features = [];
const markers = xml.getElementsByTagName('marker');
for (let i = 0; i < markers.length; i++) {
const el = markers[i];
const name = el.getElementsByTagName('name')[0].textContent;
const lat = parseFloat(el.getElementsByTagName('lat')[0].textContent);
const lng = parseFloat(el.getElementsByTagName('lng')[0].textContent);
features.push({
type: 'Feature',
properties: {
name: name
},
geometry: {
type: 'Point',
coordinates: [lng, lat]
}
});
}
return {
type: 'FeatureCollection',
features: features
};
}
Использование результата:
fetch('data/points.xml')
.then(r => r.text())
.then(str => {
const xml = new DOMParser().parseFromString(str, 'application/xml');
const geojson = xmlToGeoJSON(xml);
L.geoJSON(geojson, {
onEachFeature: function (feature, layer) {
if (feature.properties && feature.properties.name) {
layer.bindPopup(feature.properties.name);
}
}
}).addTo(map);
});
KML представляет собой XML-диалект, широко используемый в GIS. Его структура сложнее, так как включает геометрию, стили и вложенные элементы.
Пример извлечения точек из KML:
function parseKML(xml) {
const placemarks = xml.getElementsByTagName('Placemark');
const features = [];
for (let i = 0; i < placemarks.length; i++) {
const pm = placemarks[i];
const nameEl = pm.getElementsByTagName('name')[0];
const coordEl = pm.getElementsByTagName('coordinates')[0];
if (!coordEl) continue;
const coordsText = coordEl.textContent.trim();
const [lng, lat] = coordsText.split(',').map(Number);
features.push({
type: 'Feature',
properties: {
name: nameEl ? nameEl.textContent : ''
},
geometry: {
type: 'Point',
coordinates: [lng, lat]
}
});
}
return {
type: 'FeatureCollection',
features
};
}
KML может содержать линии и полигоны, где координаты представлены списками значений:
longitude,latitude,altitude longitude,latitude,altitude
Для таких случаев требуется разбор строк по пробелам и запятым.
GeoRSS представляет собой RSS/Atom с географическими расширениями. В
XML присутствуют теги вида georss:point.
<item>
<title>Объект</title>
<georss:point>51.1694 71.4491</georss:point>
</item>
Парсинг:
const items = xml.getElementsByTagName('item');
for (let i = 0; i < items.length; i++) {
const point = items[i].getElementsByTagName('georss:point')[0];
if (!point) continue;
const coords = point.textContent.split(' ');
const lat = parseFloat(coords[0]);
const lng = parseFloat(coords[1]);
L.marker([lat, lng]).addTo(map);
}
Особенностью GeoRSS является использование XML namespace, что иногда
требует работы через getElementsByTagNameNS.
Некоторые XML-документы используют namespace, например:
<georss:point xmlns:georss="http://www.georss.org/georss">
51.1694 71.4491
</georss:point>
Корректный доступ:
const ns = 'http://www.georss.org/georss';
const points = xml.getElementsByTagNameNS(ns, 'point');
Игнорирование namespace часто приводит к пустым результатам выборки.
XPath позволяет упростить выборку элементов в глубоко вложенных XML-документах.
function select(xpath, xml) {
const result = xml.evaluate(
xpath,
xml,
null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null
);
const nodes = [];
for (let i = 0; i < result.snapshotLength; i++) {
nodes.push(result.snapshotItem(i));
}
return nodes;
}
Пример:
const markers = select('//marker', xml);
XPath особенно полезен при работе с KML и сложными RSS-структурами.
После преобразования XML в структуру координат данные передаются в стандартные слои Leaflet.
Для точек:
L.geoJSON(geojson).addTo(map);
Для динамически создаваемых слоёв:
const group = L.layerGroup();
group.addLayer(L.marker([lat, lng]));
group.addTo(map);
При больших XML-файлах предпочтительно использовать
L.geoJSON, так как он оптимизирован для массового
рендеринга.
Работа с XML требует контроля ошибок парсинга и сетевых запросов.
fetch('data.xml')
.then(res => {
if (!res.ok) {
throw new Error('Ошибка загрузки');
}
return res.text();
})
.then(str => {
const xml = new DOMParser().parseFromString(str, 'application/xml');
const errorNode = xml.querySelector('parsererror');
if (errorNode) {
throw new Error('Некорректный XML');
}
return xml;
})
.catch(err => {
console.error(err);
});
При работе с XML в веб-картографии возникают типовые ограничения:
При обработке больших наборов данных важны следующие подходы:
TextDecoder и потоковую
обработку;Пример выноса парсинга:
const worker = new Worker('parser.js');
worker.postMessage(xmlString);
worker.onmess age = function(e) {
const geojson = e.data;
L.geoJSON(geojson).addTo(map);
};
Для упрощения работы с XML и форматами на его основе применяются специализированные инструменты:
Типовой подход — конвертация перед передачей в Leaflet, что снижает сложность кода и повышает предсказуемость отображения слоёв.