I am trying to extract the list of the names of available layers of a WMS server. I have done so for the GeoMet WMS by sending a GetCapabilities which returns a "application/xml" object that then I parse using a DOM parser. My problem is the Layer tags are nested on two levels. Basically the top level layer contains multiple children layers. How would I extract only the children or list of the parent Layers. I managed to hack together this by realising the children had an attribute that the parent Node did not, but there has to be a better way.
EDIT : I am interested in getting the full list of layers that can be added to an interactive map. Basically all Layer tags that do not have Layer children.
axios.get('https://geo.weather.gc.ca/geomet?lang=en&service=WMS&version=1.3.0&request=GetCapabilities').then((response) => {
// console.log(response.headers)
const parser = new DOMParser()
const dom = parser.parseFromString(response.data, 'application/xml')
let layerGroups = dom.querySelectorAll('[cascaded="0"]')
let layerNames = []
layerGroups.forEach(function (domel) { layerNames.push(domel.getElementsByTagName('Name')[0].innerHTML) })
console.log(layerNames.length)
this.mylayerlist = layerNames
})
There are a couple of ways to handle this, especially the namespaces. Here's one of them. After your dom declaration try this:
xpath = '//*[local-name()="Layer"][@cascaded="0"][not(.//*[local-name()="Layer"])]/*[local-name()="Name"]';
var targets = dom.evaluate(xpath, dom, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
let nodes = Array.from({ length: targets.snapshotLength }, (_, index) =>
console.log(targets.snapshotItem(index).innerHTML));
Output is 3,519 (in this case) of names:
CGSL.ETA_ICEC
CGSL.ETA_ICEPRS
CGSL.ETA_ICESTG
CGSL.ETA_ICET
CGSL.ETA_ICETK
The critical component here is the xpath expression. It selects all Layer
nodes which have a cascaded
attribute with a value of 0
and no Layer
child nodes. In this particular case, none of the Layer
nodes which have a cascaded
attribute (note that all of these attributes have a 0
attribute value) have Layer
children, so you could dispense with one of the two predicates (either [@cascaded="0"]
or [not(./*[local-name()="Layer"])]
and get the same output, though this may not be the case with other files).