Why doesn't XMLDocument.evaluate find nodes in this WMS GetCapabilities document - javascript

I'm trying to parse information from this XML Document.
The JavaScript below works for simple XML test docs but I cannot find XPath that will return any nodes from the real document.
he idea is just to list all the "Layer" nodes from the WMS GetCapabilities XMl Document.
What am I doing wrong?
Thanks, Code below.
<html>
<body>
<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(xhttp.responseText, "text/xml");
var iterator = xmlDoc.evaluate('Layer', xmlDoc.documentElement, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
var thisNode = iterator.iterateNext();
while (thisNode) {
documemnt.console.log(thisNode.textContent);
thisNode = iterator.iterateNext();
}
}
};
xhttp.open("GET", "https://geo.weather.gc.ca/geomet?service=WMS&request=GetCapabilities", true);
xhttp.send();
</script>
</body>
</html>

I think you need to learn how to take a default namespace into account, using the third argument of the evaluate function to map a prefix you can choose freely to the namespace the elements like the Layer or Title elements are in and to use that prefix in your XPath expressions:
var req = new XMLHttpRequest();
req.open('GET', 'https://geo.weather.gc.ca/geomet?service=WMS&request=GetCapabilities');
req.onload = function() {
var doc = this.responseXML;
var namespaces = { wms: 'http://www.opengis.net/wms' };
var result = doc.evaluate(
'/wms:WMS_Capabilities/wms:Capability//wms:Layer/wms:Title',
doc,
function(prefix) { return namespaces[prefix]; },
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
null);
var ol = document.createElement('ol');
for (var i = 0; i < result.snapshotLength; i++) {
var li = document.createElement('li');
li.textContent = result.snapshotItem(i).textContent;
ol.appendChild(li);
}
document.body.appendChild(ol);
};
req.send();

Related

xml is not a function

I have been going crazy about this for a couple hours. Can someone help me? I am getting "xmlDoc is not a function" error.
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
loadXMLDoc();
function loadXMLDoc() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myFunction(this);
}
};
xmlhttp.open("GET", "https://www.w3schools.com/xml/cd_catalog.xml", true);
xmlhttp.send();
}
function myFunction(xml) {
var item = "Bonnie Tyler";
var xmlDoc = xml.responseXML;
var x = xmlDoc('ARTIST').find(includes(item));
console.log(x);
}
try this
function myFunction(xml) {
var item = "Bonnie Tyler";
var xmlDoc = xml.responseXML;
var x = [...xmlDoc.querySelectorAll('ARTIST')].find(el=>el.textContent == item);
console.log(x);
}
your xmlDoc is xml document, not a function, you can only apply some methods on.
I have tried nearly everything works for NodeJS but found a solution by using xml2js package. Works perfectly!

XML response text is undefined

I am making a call to an external server and am getting a valid response back with data. If I dump that data into console.log() I can see the data that I'm looking for. However the returned data is XML and if I try and use the getElementsByTagName method on the response text I get the error Uncaught TypeError: searchResults.getElementsByTagName is not a function. I checked and searchResults is undefined, which I'm assuming is my problem, I'm just not sure how to fix it.
function getBggData() {
var searchTerm = document.getElementById("searchTerm").value;
// console.log("Search Term = " + searchTerm);
var httpURL = "https://www.boardgamegeek.com/xmlapi2/search?type=boardgame,boardgameexpansion&query=" + searchTerm
// console.log("URL used is = " + httpURL);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
displayData(this);
}
};
xhttp.open("GET", httpURL, true);
xhttp.send();
};
function displayData(xml) {
var i;
var searchResults = xml.responseText;
console.log(searchResults.type);
console.log(searchResults);
var table = "<tr><th>Game</th><th>Year Released</th></tr>";
var x = searchResults.getElementsByTagName("item");
document.getElementById("resultsHeader").innerHTML = "Search Results = " + x + " items.";
document.getElementById("searchResults").innerHTML = table;
};
you can do like this,
var parser = new DOMParser();
var xmlDoc = parser.parseFromString(xml,"text/xml");
console.log(xmlDoc.getElementsByTagName("title")[0]);
here we are parsing the xml and getting it to the variable xmlDoc
var searchResults = xml.responseXML;

How can I make AJAX work for me?

I make APIs all the time and I'm working on one called Swerer. Swerer is an easy and efficient way to use AJAX. Now the problem is when I use Swerer.getFile("file.txt") it returns undefined instead of the content. Any help would be appreciated.
/*
Complex.js 1.0.0
Dec 14, 2017
*/
(function(){
if(!document){
throw new Error("Complex.js needs a window with a document");
}
})();
var toString = Object.prototype.toString;
// Make X
X = function(){
};
X.extend = function(){
var target = arguments[0], obj, arg = arguments;
for (var i = 0; i < arg.length; i++) {
if(toString.call(arg[i]) == "[object Boolean]"){
if(arg[i] !== false){
if(!target){
obj = [];
}else{
for(i in target){
target[i] = obj[i];
}
}
}else{
obj = [];
}
}
}
return obj;
};
// Make constructors
X.extend({
// We are going to make something called Swerer
Swerer: function(){
X.call(this);
},
isFunction: function(obj){
if(toString.call(obj) == "[object Function]"){
return true;
}
},
});
var Swerer = X.Swerer;
Swerer = {};
// Note:
// When we are refering to Swerer in a Swerer function we can use the keyword 'this'
/*
Swerer.get("file.type", function(){
func(arg);
});
*/
// Xhr (XML Http Request) is built into Swerer
(XMLHttpRequest) ? Swerer.xhr = new XMLHttpRequest() : Swerer.xhr = new ActiveXObject("Microsoft.XMLHTTP");
Swerer.getFile = function(file){
var xhttp = this.xhr, content;
if(this.readyState == 4 && this.status == 200){
content = this.responseText;
}
xhttp.open("GET", file, true);
xhttp.send();
return content;
};
If you see any problems post a jsfiddle and I'll try to fix it. Thank you!
I must admit that I only focus on the XHR part of the code, but that should look something like this:
// Xhr (XML Http Request) is built into Swerer
(XMLHttpRequest) ? Swerer.xhr = new XMLHttpRequest() : Swerer.xhr = new ActiveXObject("Microsoft.XMLHTTP");
Swerer.getFile = function(file){
var xhttp = this.xhr;
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
return xhttp.responseText;
}
};
xhttp.open("GET", file, true);
xhttp.send();
};

Processing Server XML Response

So I'm studying for an exam and I only have a quick question that has been buggin me for a while. I use AJAX to obtain a XML file to parse it and insert its values into a select element. This is the code:
<html>
<head>
</head>
<body>
<button onclick="EnviaPedido()">Submeter</button>
<select id="select"></select>
<script type="text/javascript">
var xmlHttpObj;
function CreateXmlHttpRequestObject() {
if (window.XMLHttpRequest) {
xmlHttpObj = new XMLHttpRequest()
}
else if (window.ActiveXObject) {
xmlHttpObj = new ActiveXObject("Microsoft.XMLHTTP")
}
return xmlHttpObj;
}
function EnviaPedido() {
xmlHttpObj = CreateXmlHttpRequestObject();
xmlHttpObj.open("POST", "agenda.xml", true);
xmlHttpObj.onreadystatechange = ProcessaReposta;
xmlHttpObj.send();
}
function ProcessaReposta() {
if (xmlHttpObj.readyState == 4 && xmlHttpObj.status == 200) {
var response = xmlHttpObj.responseText;
var xmlDoc;
if (window.DOMParser) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(response, "text/xml");
} else {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(response);
}
var select = document.getElementById("select");
var centrosInvestigacao = xmlDoc.getElementsByTagName("centro_de_investigacao");
for(i = 0; i < centrosInvestigacao.length; i++) {
var option = document.createElement("option");
option.innerHTML = centrosInvestigacao[i].childNodes[1].textContent;
select.appendChild(option);
}
}
}
</script>
<body>
</html>
And this is the XML that is returned:
<FCT>
<centro_de_investigacao id="1">
<nome>GECAD</nome>
<local>ISEP</local>
<classificao>Muito bom</classificao>
</centro_de_investigacao>
<centro_de_investigacao id="2">
<nome>DEF</nome>
<local>ISEP</local>
<classificao>Bom</classificao>
</centro_de_investigacao>
<centro_de_investigacao id="3">
<nome>ABC</nome>
<local>FEUP</local>
<classificao>Muito mau</classificao>
</centro_de_investigacao>
</FCT>
So when I want to obtain the 'nome' field why do I have to use
option.innerHTML = centrosInvestigacao[i].childNodes[1].textContent;
instead of
option.innerHTML = centrosInvestigacao[i].childNodes[0].textContent;
I know it's probably a stupid question but it's starting to piss me off not knowing if this is the expected behaviour or if I'm somehow screwing this up.
Thanks.
I made a small snipset of the problem that also shows part of the answer. I would think that the encoding of the XML document you are parsing is "off", in that sence that the first element of your childNodes, is actually a textnode between the last quote of centro_de_investigacao> and the start tag of <nome.
If you check the snipset (you can play around with the index parameter for example), you would see that the first button doesn't need the index increase to 1, but can work as expected with the first element, nl the one at index 0.
So remove the whitespaces from your XML document, and you should be fine.
Whitespaces: tab, space, newline
// mocked, no real data
var xmlHttpObj;
function CreateXmlHttpRequestObject() {
function Mock() {
this.callready = function() {
this.readyState = 4;
this.status = 200;
this.statusMsg = "OK";
if (this.onreadystatechange && this.onreadystatechange.call) {
setTimeout(this.onreadystatechange.bind(this), 0);
}
};
this.open = function(methodType, url, async) {
var el = document.getElementById('dataXml-' + url.split('.')[0]),
content = el ? el.innerHTML : '';
if (typeof async === 'undefined' || async) {
// no action till send is executed
this.responseText = content;
this.responseXml = content;
return;
}
return content;
};
this.send = function(data) {
this.callready();
};
}
return new Mock();
}
function EnviaPedido(index, url) {
xmlHttpObj = CreateXmlHttpRequestObject();
xmlHttpObj.open("POST", url, true);
xmlHttpObj.onreadystatechange = ProcessaReposta.bind(this, index);
xmlHttpObj.send();
}
function ProcessaReposta(index, url) {
if (xmlHttpObj.readyState == 4 && xmlHttpObj.status == 200) {
var response = xmlHttpObj.responseText;
var xmlDoc;
if (window.DOMParser) {
parser = new DOMParser();
xmlDoc = parser.parseFromString(response, "text/xml");
} else {
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(response);
}
var select = document.getElementById("select");
var centrosInvestigacao = xmlDoc.getElementsByTagName("centro_de_investigacao");
select.options = [];
for (i = 0; i < centrosInvestigacao.length; i++) {
var option = new Option();
var item = centrosInvestigacao[i].childNodes[index];
option.text = item.textContent;
select.options[i] = option;
}
}
}
<template id="dataXml-agenda"><FCT><centro_de_investigacao id="1"><nome>GECAD</nome><local>ISEP</local><classificao>Muito bom</classificao></centro_de_investigacao><centro_de_investigacao id="2"><nome>DEF</nome><local>ISEP</local><classificao>Bom</classificao></centro_de_investigacao><centro_de_investigacao id="3"><nome>ABC</nome><local>FEUP</local><classificao>Muito mau</classificao></centro_de_investigacao></FCT></template>
<template id="dataXml-original-agenda"><FCT>
<centro_de_investigacao id="1">
<nome>GECAD</nome>
<local>ISEP</local>
<classificao>Muito bom</classificao>
</centro_de_investigacao>
<centro_de_investigacao id="2">
<nome>DEF</nome>
<local>ISEP</local>
<classificao>Bom</classificao>
</centro_de_investigacao>
<centro_de_investigacao id="3">
<nome>ABC</nome>
<local>FEUP</local>
<classificao>Muito mau</classificao>
</centro_de_investigacao>
</FCT></template>
<select id="select"></select>
<button id="btnGenerate" type="button" onclick="EnviaPedido(0, 'agenda.xml');">Get info</button>
<button id="btnGenerate" type="button" onclick="EnviaPedido(1, 'original-agenda.xml');">Get info false contentType</button>

create object from processor output to append/replaceChild

Attempting to add parameters to an xsl template, for use in a navigation menu.
Trying to figure out how to use the output that IXSLProcessor leaves me with.
I have the following code that works perfectly for Firefox
var xslStylesheet;
var xsltProcessor = new XSLTProcessor();
var myDOM;
var xmlDoc;
var myXMLHTTPRequest = new XMLHttpRequest();
myXMLHTTPRequest.open("GET", "client.xsl", false);
myXMLHTTPRequest.send(null);
xslStylesheet = myXMLHTTPRequest.responseXML;
xsltProcessor.importStylesheet(xslStylesheet);
// load the xml file
myXMLHTTPRequest = new XMLHttpRequest();
myXMLHTTPRequest.open("GET", "client.xml", false);
myXMLHTTPRequest.send(null);
xmlDoc = myXMLHTTPRequest.responseXML;
// set the parameter using the parameter passed to the outputgroup function
xsltProcessor.setParameter(null, "cid", client);
xsltProcessor.setParameter(null, "browser", "other");
var fragment = xsltProcessor.transformToFragment(xmlDoc,document);
document.getElementById("scriptHook").innerHTML = "";
document.getElementById("maincontent").replaceChild(fragment, document.getElementById("scriptHook"));
scroll(0,0);
This is the code I have (mostly pilfered from msdn)
var xslt = new ActiveXObject("Msxml2.XSLTemplate.3.0");
var xsldoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument.3.0");
var xslproc;
xsldoc.async = false;
xsldoc.load("client.xsl");
if (xsldoc.parseError.errorCode != 0) {
var myErr = xsldoc.parseError;
WScript.Echo("You have error " + myErr.reason);
} else {
xslt.stylesheet = xsldoc;
var xmldoc = new ActiveXObject("Msxml2.DOMDocument.3.0");
xmldoc.async = false;
xmldoc.load("client.xml");
if (xmldoc.parseError.errorCode != 0) {
var myErr = xmldoc.parseError;
WScript.Echo("You have error " + myErr.reason);
} else {
xslproc = xslt.createProcessor();
xslproc.input = xmldoc;
xslproc.addParameter("cid", client);
xslproc.addParameter("browser", "ie");
xslproc.transform();
//somehow convert xslproc.output to object that can be used in replaceChild
document.getElementById("scriptHook").innerHTML = "";
document.getElementById("maincontent").replaceChild(xslproc.output, document.getElementById("scriptHook"));
}
}
Any and all help is appreciated, cheers.
With Mozilla you can exchange nodes between XSLT and DOM but with IE you need to take the XSLT transformation result as a string and feed that to IE's HTML parser; so for your sample I think you want
document.getElementById("scriptHook").outerHTML = xslproc.output;
which will replace the scriptHook element with the result of the transformation.

Categories

Resources