Quiero comenzar diciendo que entiendo que hay muchas preguntas similares (en la pila y en otros sitios) relacionadas con este problema, pero he pasado las últimas horas recorriendo cada rincón de Internet y todavía estoy saliendo seco.
Como referencia, examiné los siguientes sitios que me brindaron orientación, pero en general me dejaron más confundido que antes:
https://humanwhocodes.com/blog/2009/03/24/xpath-in-javascript-part-2/
Javascript Xpath y espacios de nombres predeterminados
Dame un ejemplo de cómo realizar una consulta xpath en un documento KML, desde Javascript
XPath y espacios de nombres
Muy bien, a la pregunta. Estoy usando Javascript y XPath para intentar leer un archivo KML. Uso FileReader para obtener el contenido del archivo XML, luego uso el siguiente código para intentar acceder a los nodos XML que se encuentran dentro.
const xmlParser = new DOMParser(); const xml = xmlParser.parseFromString(contents,"text/xml"); // Contents variable contains the contents of the file (as read by FileReader) // Read XML if (xml.evaluate) { // Most major browsers (except IE) var path = "/kml/Document/Folder[1]/Placemark/Point/coordinates"; var evaluator = new XPathEvaluator(); var resolver = evaluator.createNSResolver(xml.documentElement); var nodes = xml.evaluate(path, xml.documentElement, resolver, XPathResult.ANY_TYPE, null); var result = nodes.iterateNext(); while (result) { console.log(result); result = nodes.iterateNext(); } }Mi archivo KML comienza con:
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2"> <Document> <name>-/XDF</name> De esto entiendo que la propiedad xmlns define el espacio de nombres. Mi código Javascript funciona como se esperaba cuando elimino esta propiedad del nodo (ya que el archivo ya no usa un espacio de nombres), lo que me lleva a creer que el problema es que no estoy definiendo un espacio de nombres correcto para usar XPath.
La variable de resolver es algo que copié de uno de los sitios vinculados anteriormente. He intentado encontrar una referencia adecuada sobre cómo generar un solucionador de espacio de nombres, pero no puedo encontrar algo que funcione con mi archivo KML.
¿Alguien con más experiencia en esta área puede orientarme en la dirección correcta para generar un objeto de espacio de nombres que me permita leer el archivo KML?
Gracias a @dandavis por el aviso.
Necesitaba crear una función separada para devolver el espacio de nombres fijo:
function resolver() { return 'http://www.opengis.net/kml/2.2'; } y haga referencia a mi ruta XPath con myns: prefijo para cada nodo.
var path = "//myns:Document/myns:Folder[1]/myns:Placemark/myns:Point/myns:coordinates"; A continuación se muestra la rutina modificada (que hace referencia a la función de resolver anterior) en caso de que ayude a alguien más:
const xmlParser = new DOMParser(); const xml = xmlParser.parseFromString(contents,"text/xml"); // Read XML if (xml.evaluate) { // Most major browsers (except IE) var path = "//myns:Document/myns:Folder[1]/myns:Placemark/myns:Point/myns:coordinates"; var nodes = xml.evaluate(path, xml.documentElement, resolver, XPathResult.ANY_TYPE, null); var result = nodes.iterateNext(); while (result) { console.log(result); result = nodes.iterateNext(); } }Con XPath 2 y versiones posteriores compatibles con Saxon-JS 2 ( https://www.saxonica.com/saxon-js/documentation/index.html#!api/xpathEvaluate ), puede mantener sus rutas XPath a elementos compactos y con prefijo. menos declarando espacios de nombres predeterminados para la evaluación de XPath
var path = '//Document/Folder[1]/Placemark/Point/coordinates'; var result = SaxonJS.XPath.evaluate(path, xml, { xpathDefaultNamespace : 'http://www.opengis.net/kml/2.2' }); console.log(result);