Processing Server XML Response - javascript

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>

Related

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

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();

How to select a random child element from XML & show sub-child elements; using JS?

I want to take data from an XML file to display in an html page that is obtained by clicking a button. When the button is clicked, I'd like it to select a random child, and display the sub-child data. I made an XML file that looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<kdramas>
<kdrama>
<title lang="en">A Gentleman's Dignity</title>
<genre>Comedy, Romance, Drama</genre>
<year>2012</year>
<episodes>20</episodes>
<about>This drama will tell the story of four men in their forties as they go through love, breakup, success and failure. </about>
</kdrama>
<kdrama>
<title lang="en">Boys Over Flowers</title>
<genre>Comedy, Romance, Drama, School</genre>
<year>2009</year>
<episodes>25</episodes>
<about>about text</about>
</kdrama>
<kdrama>
<title lang="en">Goblin</title>
<genre>Comedy, Romance, Melodrama, Supernatural</genre>
<year>2016</year>
<episodes>16</episodes>
<about>about text</about>
</kdrama>
I am able to display the XML data when the button is clicked, but it shows all of the data (except for the titles). I have looked around to see if it is possible to select a random child then display its sub-child elements, but so far, I am not having any luck finding anything. The JS code I have to display the XML data is:
function getDrama(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("content").innerHTML =
this.responseText;
document.getElementById("content").style.display = "block";
}
};
xhttp.open("GET", "https://raw.githubusercontent.com/npellow/npellow.github.io/master/kdramaList.xml", true);
xhttp.send();
}
Any ideas on how to do this? Or even just pointing me to a place where I can read on how to do it myself would be great?
Use JQuery construction $(_your_text_).find('_elenent_name_') for find data:
function getDrama(_callback){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//document.getElementById("content").innerHTML = this.responseText;
//document.getElementById("content").style.display = "block";
_callback(this.responseText);
}
};
xhttp.open("GET", "https://raw.githubusercontent.com/npellow/npellow.github.io/master/kdramaList.xml", true);
xhttp.send();
}
function get_random_title(){
getDrama(function(_text){
var titles_length = $(_text).find('kdrama').length;
var random_number = 1 + Math.floor(Math.random() * titles_length);
var random_title = $(_text).find('kdrama').eq(random_number).find('title').text();
$('#content').html( random_title );
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="content"></div>
<input type="button" value="Get Random Title" onClick="get_random_title();">
I suggest converting the XML to JSON for easier handling, you can use the function found here https://davidwalsh.name/convert-xml-json
You get the array of kdramas and then select a random element. Just need to format the JSON for printing.
function xmlToJson( xml ) {
// Create the return object
var obj = {};
if ( xml.nodeType == 1 ) { // element
// do attributes
if ( xml.attributes.length > 0 ) {
obj["#attributes"] = {};
for ( var j = 0; j < xml.attributes.length; j++ ) {
var attribute = xml.attributes.item( j );
obj["#attributes"][attribute.nodeName] = attribute.nodeValue;
}
}
} else if ( xml.nodeType == 3 ) { // text
obj = xml.nodeValue;
}
// do children
if ( xml.hasChildNodes() ) {
for( var i = 0; i < xml.childNodes.length; i++ ) {
var item = xml.childNodes.item(i);
var nodeName = item.nodeName;
if ( typeof(obj[nodeName] ) == "undefined" ) {
obj[nodeName] = xmlToJson( item );
} else {
if ( typeof( obj[nodeName].push ) == "undefined" ) {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push( old );
}
obj[nodeName].push( xmlToJson( item ) );
}
}
}
return obj;
}
function getDramaList(callback){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var xmlDOM = new DOMParser().parseFromString(this.responseText, 'text/xml');
var jsonXml = xmlToJson(xmlDOM);
callback(jsonXml.kdramas.kdrama);
}
};
xhttp.open("GET", "https://raw.githubusercontent.com/npellow/npellow.github.io/master/kdramaList.xml", true);
xhttp.send();
}
getDramaList(function(dramaList){
var randomIndex = Math.floor(Math.random(0,dramaList.length));
var randomKdrama = dramaList[randomIndex];
document.getElementById("content").innerHTML = JSON.stringify(randomKdrama, null, " ").replace(/\n/g,"<br>");
document.getElementById("content").style.display = "block";
});
<div id="content">
</div>

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.

Adding XML element using Jquery

I have been working on adding XML element to XML structure without success, here is my code.
var parseXml;
if (window.DOMParser) {
parseXml = function(xmlStr) {
return ( new window.DOMParser() ).parseFromString(xmlStr, "text/xml");
};
}
else if (typeof window.ActiveXObject != "undefined" && new window.ActiveXObject("Microsoft.XMLDOM")) {
parseXml = function(xmlStr) {
var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = "false";
xmlDoc.loadXML(xmlStr);
return xmlDoc;
};
}
else {
parseXml = function() { return null; }
}
var xmlTree = parseXml("<root></root>");
function add_children(child_name,parent_name)
{
str = '<'+child_name+'></'+child_name+'>';
//strXML = parseXml(str);
$(xmlTree).find(parent_name).append(str);
var xmlString = (new XMLSerializer()).serializeToString(xmlTree);
console.log(xmlString);
}
add_children("apple","root");
add_children("orange","root");
add_children("lychee","root");
but console is showing <root/> all three times
The problem is that you are creating the node in the Html document, not in the XML one, so you can't append it. Change this line:
str = '<'+child_name+'></'+child_name+'>';
For this one:
str = xmlTree.createElement(child_name);
See the working code in http://jsfiddle.net/W9Wpb/

Reading xml document in firefox

I am trying to read customers.xml using javascript.
My professor has taught us to read xml using `ActiveXObjectand he has given us an assignment to create a sample login page which checks username and password by reading customers.xml.
I am trying to use DOMParser so that it works with firefox.
But when I click on Login button I get this error.
Error: syntax error Source File:
file:///C:/Users/Searock/Desktop/home/project/project/login.html
Line: 1, Column: 1 Source Code:
customers.xml
Here's my code.
login.js
var xmlDoc = 0;
function checkUser()
{
var user = document.login.txtLogin.value;
var pass = document.login.txtPass.value;
//xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
/*
xmlDoc = document.implementation.createDocument("","",null);
xmlDoc.async = "false";
xmlDoc.onreadystatechange = redirectUser;
xmlDoc.load("customers.xml");
*/
var parser = new DOMParser();
xmlDoc = parser.parseFromString("customers.xml", "text/xml");
alert(xmlDoc.documentElement.nodeName);
xmlDoc.async = "false";
xmlDoc.onreadystatechange = redirectUser;
}
function redirectUser()
{
alert('');
var user = document.login.txtLogin.value;
var pass = document.login.txtPass.value;
var log = 0;
if(xmlDoc.readyState == 4)
{
xmlObj = xmlDoc.documentElement;
var len = xmlObj.childNodes.length;
for(i = 0; i < len; i++)
{
var nodeElement = xmlObj.childNodes[i];
var userXml = nodeElement.childNodes[0].firstChild.nodeValue;
var passXml = nodeElement.childNodes[1].firstChild.nodeValue;
var idXML = nodeElement.attributes[0].value
if(userXml == user && passXml == pass)
{
log = 1;
document.cookie = escape(idXML);
document.login.submit();
}
}
}
if(log == 0)
{
var divErr = document.getElementById('Error');
divErr.innerHTML = "<b>Login Failed</b>";
}
}
customers.xml
<?xml version="1.0" encoding="UTF-8"?>
<customers>
<customer custid="CU101">
<user>jack</user>
<pwd>PW101</pwd>
<email>jack#rediff.com</email>
</customer>
<customer custid="CU102">
<user>jill</user>
<pwd>PW102</pwd>
<email>jill#rediff.com</email>
</customer>
<customer custid="CU103">
<user>john</user>
<pwd>PW103</pwd>
<email>john#rediff.com</email>
</customer>
<customer custid="CU104">
<user>jeff</user>
<pwd>PW104</pwd>
<email>jeff#rediff.com</email>
</customer>
</customers>
I get parsererror message on line alert(xmlDoc.documentElement.nodeName);
I don't know what's wrong with my code. Can some one point me in a right direction?
Edit :
Ok, I found a solution.
var xmlDoc = 0;
var xhttp = 0;
function checkUser()
{
var user = document.login.txtLogin.value;
var pass = document.login.txtPass.value;
var err = "";
if(user == "" || pass == "")
{
if(user == "")
{
alert("Enter user name");
}
if(pass == "")
{
alert("Enter Password");
}
return;
}
if (window.XMLHttpRequest)
{
xhttp=new XMLHttpRequest();
}
else // IE 5/6
{
xhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.onreadystatechange = redirectUser;
xhttp.open("GET","customers.xml",true);
xhttp.send();
}
function redirectUser()
{
var log = 2;
var user = document.login.txtLogin.value;
var pass = document.login.txtPass.value;
if (xhttp.readyState == 4)
{
log = 0;
xmlDoc = xhttp.responseXML;
var xmlUsers = xmlDoc.getElementsByTagName('user');
var xmlPasswords = xmlDoc.getElementsByTagName('pwd');
var userLen = xmlDoc.getElementsByTagName('customer').length;
var xmlCustomers = xmlDoc.getElementsByTagName('customer');
for (var i = 0; i < userLen; i++)
{
var xmlUser = xmlUsers[i].childNodes[0].nodeValue;
var xmlPass = xmlPasswords[i].childNodes[0].nodeValue;
var xmlId = xmlCustomers.item(i).attributes[0].nodeValue;
if(xmlUser == user && xmlPass == pass)
{
log = 1;
document.cookie = xmlId;
document.login.submit();
break;
}
}
}
if(log == 0)
{
alert("Login failed");
}
}
Thanks.
parseFromString is parsing the string "customer.xml" in your case, because the first argument needs to be a string containing the actual content of the XML document and not its name.
You can use something like this to get the xml file:
if (window.XMLHttpRequest)
{
xhttp=new XMLHttpRequest();
}
else // IE 5/6
{
xhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xhttp.open("GET","customer.xml",false);
xhttp.send();
xmlDoc=xhttp.responseXML;
Source

Categories

Resources