Read XML node using ajax - javascript

I need to use ajax to read xml node values and use those values further in existing JavaScript function.
Sample XML -
<cars>
<car mfgdate="1 Jan 15" name="Ford" id="1">
<engine litres="3.0" cylinders="6"/>
</car>
<car mfgdate="1 Feb 15" name="Toyota" id="2">
<engine litres="2.2" cylinders="4"/>
</car>
</cars>
Here I need to display details of one car (Ex.Ford) at a time on screen.
There are separate fields on UI to display details like name, mfgdate, litres and cylinders.
If user press next button then next car(Ex. Toyota) details should appear on screen. I need to make ajax calls to do it.
Any help is much appreciated.
Thanks.
Ajax Call
$(document).ready(function(){
$.ajax({ type: "GET",
url: "Cars.xml",
dataType: "xml",
success: function (xml) {
var xmlDoc = $.parseXML(xml);
$xml = $(xmlDoc);
$xml.find('events event date').each(function () {
alert($(this).text() + "<br />");
});
}
});
});

You can find here an example but you have just to put the parse part inside your ajax response call (and also for use as you designed your style ) :
var xmlString = '<cars>'+
'<car mfgdate="1 Jan 15" name="Ford" id="1">'+
'<engine litres="3.0" cylinders="6"/>'+
'</car>'+
'<car mfgdate="1 Feb 15" name="Toyota" id="2">'+
'<engine litres="2.2" cylinders="4"/>'+
'</car>'+
'<car mfgdate="1 Jan 16" name="SONACOM" id="3">'+
'<engine litres="4.0" cylinders="8"/>'+
'</car>'+
'</cars>';
// used to inc or decrements throw cars
var i = 0;
$(document).ready(function(){
xml = $.parseXML( xmlString );
$xml = $( xml );
$cars = $xml.find( "car" );
getCar($cars)
$("#btnnext").click(function(){
i++;
getCar($cars);
})
$("#btnprev").click(function(){
i--;
getCar($cars);
})
function getCar(cars) {
var html ="";
if(cars.length != 'undefined') {
if(cars.length > 0) {
if(i<cars.length){
var name = $(cars[i]).attr('name');
var mfgdate = $(cars[i]).attr('mfgdate')
var $engine = $(cars[i]).find('engine');
var litres = $($engine).attr('litres');
var cylinders = $($engine).attr('cylinders');
html += "<div>Name : "+name+"</div>";
html += "<div>Mfgdate : "+mfgdate+"</div>";
html += "<div>Litres : "+litres+"</div>";
html += "<div>Cylinders : "+cylinders+"</div>";
$("#carinfo").html(html);
btnClick();
}
}
}
}
function btnClick() {
i == 0 ? $("#btnprev").attr("disabled","disabled") :$("#btnprev").removeAttr("disabled");
i == $cars.length-1 ? $("#btnnext").attr("disabled","disabled") : $("#btnnext").removeAttr("disabled");
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="btnprev" disabled>prev</button>
<button id="btnnext" disabled>next</button>
<br> <br>
<div id ="carinfo">
</div>

Related

Why my ajax function cannot append html at targeted div element?

I am submitting a html form through AJAX and then appending results at particular div element.The corresponding ajax is :-
$(document).ready(function(){
$('.commentbutton').click(function(){
var idb=$(this).attr('id');
var formid=$('#Comment'+idb);
datab=getFormData(formid);
$.ajax({
type:"POST",
url:'/submit/channelcomment',
data:datab,
success:function(data){
console.log(data.content);
console.log(data.profile);
var html="<div class='CommentRow'><a href='/Channel/"+data.profile+"/'style='font-weight: bolder;margin-right: 10px;display: inline-block;'>"+data.profile+"</a>"+data.content+"</div>"
console.log('Done');
idt=$('#CommentBody'+idb);
console.log(idt);
idt.append(html);
},
}),
event.preventDefault();
});
});
function getFormData($form){
var unindexed_array = $form.serializeArray();
var indexed_array = {};
$.map(unindexed_array, function(n, i){
indexed_array[n['name']] = n['value'];
});
return indexed_array;
}
The desired position at which i'm trying to append html is as follows:-
<div class="CommentBody" id="CommentBody{{c.id}}">
</div>
Here c.id and idb equals to 1.But it is not appending html.
When you say
But it is not appending html.
What is actual behavior?
I tried the dummy code as below and it is working fine.
$(document).ready(function() {
$('.commentbutton').click(function() {
var html = "<div class='CommentRow'><a href='/Channel/data.profile/'style='font-weight: bolder;margin-right: 10px;display: inline-block;'>data.profile</a>data.content</div>"
var idb = '1';
idt = $('#CommentBody' + idb);
alert(idt);
idt.append(html);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class='commentbutton'>Comment</button>
<div class="CommentBody" id="CommentBody1">
</div>

How do you for each on XML data

Im trying to grab the channel display name and channel id from some XML data but it cant seem to get it to work. For each channel display name I what to grab the channel display name and channel id, this is what I have tried, it grabs the data but it puts them all into one string and I want them on separate lines.
var xml = "<tv generator-info-name='tvchannels' source-info-name='tvchannels'><channel id='1234'><display-name>Channel 1</display-name></channel><channel id='5678'><display-name>Channel 2</display-name></channel><channel id='543553'><display-name>Channel 3</display-name></channel><channel id='324324'><display-name>Channel 4</display-name></channel></tv>",
xmlDoc = $.parseXML( xml ),
$xml = $( xmlDoc );
$xml.find("display-name").each(
function (i,e) {
$('#title').append($xml.find("display-name"));
$('#channelid').append($xml.find("channel").attr("id"));
});
XPATH and XSL/XSLT do this, however they can be difficult to learn/use compared to javascript/JSON. JavaScript Object Notation, JSON, is preferred. Have a look at
XPath Examples from Microsoft
Introduction to using XPath in JavaScript from MDN.
Iterator Example
var iterator = document.evaluate('//phoneNumber', documentNode, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null );
try {
var thisNode = iterator.iterateNext();
while (thisNode) {
alert( thisNode.textContent );
thisNode = iterator.iterateNext();
}
}
catch (e) {
alert( 'Error: Document tree modified during iteration ' + e );
}
When you're looping through $xml, you need to use $(this) or the second argument passed to .each() in order to access the individual channels as you're looping through. See the code below:
var xml = "<tv generator-info-name='tvchannels' source-info-name='tvchannels'><channel id='1234'><display-name>Channel 1</display-name></channel><channel id='5678'><display-name>Channel 2</display-name></channel><channel id='543553'><display-name>Channel 3</display-name></channel><channel id='324324'><display-name>Channel 4</display-name></channel></tv>",
xmlDoc = $.parseXML( xml ),
$xml = $( xmlDoc );
$xml.find('channel').each(function (i,e) {
$('#title').append($(this).find("display-name"));
$('#title').append($('<br />'));
$('#channelid').append($(this).attr("id"));
$('#channelid').append($('<br />'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Titles: <br />
<div id="title"></div><br />
Channel IDs: <br />
<div id="channelid"></div>
You are not using the results of the find method. I believe you need smth like
var xml = "<tv generator-info-name='tvchannels' source-info-name='tvchannels'><channel id='1234'><display-name>Channel 1</display-name></channel><channel id='5678'><display-name>Channel 2</display-name></channel><channel id='543553'><display-name>Channel 3</display-name></channel><channel id='324324'><display-name>Channel 4</display-name></channel></tv>",
xmlDoc = $.parseXML( xml ),
$xml = $( xmlDoc );
$xml.find("channel").each(function(index, e) {
$('#title').append($(e).find("display-name").text() + '<br />');
$('#channelid').append(e.getAttribute("id") + '<br />');
});
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<div id="title"></div>
<div id="channelid"></div>

form to modify XML data using Xpath

I'm trying to setup a form to allow people modifying some parts of XML files, using standard inputs/textareas/checkboxes, etc; and see the corresponding XML file modified in "real time", in their browser (so using JS)
What I have been doing so far is have an attribute on each form element that stores an XPath to see which XML node/text the input corresponds to.
I can get the xpath value from the XML, but them I'm unable to modify the corresponding XML.
Here is the code :
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
function updateXml(input) {
newvalue = $(input).val();
xmlStr = $("#xml" ).val();
if(xmlStr=="" ) return;
xmlObj = $.parseXML(xmlStr);
xpath = $(input).attr('data-xpath');
result = xmlObj.evaluate(xpath, xmlObj, null, XPathResult.ANY_TYPE, null);
element = result.iterateNext();
//element is a copy of the noden I can't modify it directly, it won't be reflected in xmlObj...
//this will work in my example, but it's too "hardcoded", I want to change that using xpath
xmlObj.getElementsByTagName("person" )[0].getElementsByTagName("name" )[0].innerHTML = newvalue;
var xmlText = new XMLSerializer().serializeToString(xmlObj);
$("#xml" ).val(xmlText);
}
</script>
<form>
<input onkeyup="updateXml(this);" data-xpath="/person/name" />
<textarea id="xml" style="width: 800px;height: 600px;">
<?xml version="1.0" encoding="ISO-8859-1"?>
<person>
<name>Paul</name>
<age>12</age>
</person>
</textarea>
</form>
In other words, I would like to be able to change the "age" using another input field, without changing the code...
Any idea how I can do this ? or another (simple) way of doing it ?
Thanks !
Your basic idea is correct: manipulate the document using the XML DOM elements, then serialize back and update the textarea.
The sample code below is still incomplete and needs some polishment before it can go to production. However, I think I have added a lot of useful code and demonstrated how it can be done!
function getElementsByXPath(xpath, elt, val)
{
var results = [];
var nsResolver = document.createNSResolver( elt.ownerDocument == null ? elt.documentElement : elt.ownerDocument.documentElement );
var xPathRes = document.evaluate(xpath, elt, nsResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < xPathRes.snapshotLength; i++) {
var element = xPathRes.snapshotItem (i);
if (element instanceof Attr) { results.push(val); }//element.nodeValue);
else if (element instanceof Element && element.outerHTML) { element.innerHTML = val;
results.push(element.outerHTML);}
else results.push(element); //TODO
}
return results;
}
function updateXml(input) {
newvalue = $(input).val();
xmlStr = $("#xml" ).val();
if(xmlStr=="" ) return;
var xml = (new DOMParser()).parseFromString(xmlStr, "text/xml");
var xpath = $(input).attr('data-xpath');
var results = getElementsByXPath(xpath, xml, newvalue);
/*var ResultTxt = '';
results.forEach(function(result) {
ResultTxt += result + "\n";
});
$("#result" ).val(ResultTxt);
console.log(ResultTxt);*/
var xmlText = new XMLSerializer().serializeToString(xml);
$("#xml" ).val(xmlText);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
<form>
<input onkeyup="updateXml(this);" data-xpath="/person/name" />
<textarea id="xml" style="width: 800px;height: 200px;">
<?xml version="1.0" encoding="ISO-8859-1"?>
<person>
<name>Paul</name>
<age>12</age>
</person>
</textarea>
</form>
</body>
</html>

Generating a table with jQuery with XML data

I am new to jQuery, and js for that matter. I am trying to create a table from XML data, but I can't get the output correct. Here is what I have so far:
HTML:
<table id="daily_fruit">
<tbody>
</tbody>
</table>
jQuery:
var xml = '<daily_fruit><day>Mon</day><type>apple</type><day>Tues</day><type>orange</type><day>Wed</day><type>banana</type><day>Thur</day><type>pear</type></daily_fruit>';
xmlDoc = $.parseXML(xml),
$xml = $(xmlDoc);
$($xml).each(function() {
var showTimes = $xml.find('daily_fruit').each(function() {
var $day = $(this).find('day').text();
var $type = $(this).find("type").text();
$("#daily_fruit").find('tbody')
.append($('<tr>')
.append($('<td>')
.append($day))
)
.append($('<td>')
.append($type))
});
});
Current Output:
MonTuesWedThur
appleorangebananapear
Desired Output:
Mon apple
Tues orange
Wed banana
Thur pear
I think I am close, but I just can't figure it out.
Try modifying your XML so that each fruit is within its own tag. Then instead of finding the "daily_fruit" tag for your each loop, use the "fruit" tag.
Here's a jsfiddle:
https://jsfiddle.net/57wgab88/
var xml = '<daily_fruit><fruit><day>Mon</day><type>apple</type></fruit><fruit><day>Tues</day><type>orange</type></fruit><fruit><day>Wed</day><type>banana</type></fruit><fruit><day>Thur</day><type>pear</type></fruit></daily_fruit>';
xmlDoc = $.parseXML(xml),
$xml = $(xmlDoc);
$($xml).each(function() {
var showTimes = $xml.find('fruit').each(function() {
var $day = $(this).find('day').text();
var $type = $(this).find("type").text();
$("#daily_fruit").find('tbody')
.append($('<tr>')
.append($('<td>')
.append($day))
.append($('<td>')
.append($type))
)
});
});
Given such XML structure, you're supposed to iterate through <day> elements instead. Assuming that each <day> is always followed by corresponding <type> element :
var xml = '<daily_fruit><day>Mon</day><type>apple</type><day>Tues</day><type>orange</type><day>Wed</day><type>banana</type><day>Thur</day><type>pear</type></daily_fruit>';
xmlDoc = $.parseXML(xml),
$xml = $(xmlDoc);
$($xml).each(function() {
var showTimes = $xml.find('day').each(function() {
var $day = $(this).text();
var $type = $(this).next("type").text();
$("#daily_fruit").find('tbody')
.append($('<tr>')
.append($('<td>')
.append($day))
.append($('<td>')
.append($type))
)
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="daily_fruit">
<tbody>
</tbody>
</table>

Loop through XML Parser?

I am developing an app, where on the click of a button, a list of the document information stored in an XML file is shown on screen in a <ul> tag. The current JavaScript in the function is;
function viewXMLFiles() {
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "TestInfo.xml", false);
xmlhttp.send();
xmlDoc = xmlhttp.responseXML;
document.getElementById("docname").innerHTML = xmlDoc.getElementsByTagName("document_name")[0].childNodes[0].nodeValue;
document.getElementById("filetype").innerHTML = xmlDoc.getElementsByTagName("file_type")[0].childNodes[0].nodeValue;
document.getElementById("fileloc").innerHTML = pathToRoot + "/" + document.getElementById("docname").innerHTML;
document.getElementById("docname1").innerHTML = xmlDoc.getElementsByTagName("document_name")[1].childNodes[0].nodeValue;
document.getElementById("filetype1").innerHTML = xmlDoc.getElementsByTagName("file_type")[1].childNodes[0].nodeValue;
document.getElementById("fileloc1").innerHTML = pathToRoot + "/" + document.getElementById("docname1").innerHTML;
}
but i want to set it so that even if more file information is added, the function will display it too. i have already looked at Jquery xml parsing loops this question, but i couldn't get the function to work. Here's the XML file;
<document_list>
<document>
<document_name>Holidays.pdf</document_name><br />
<file_type>.pdf</file_type> <br />
<file_location>TEST</file_location> <br />
</document>
<document>
<document_name>iPhone.jsNotes.docx</document_name><br />
<file_type>.docx</file_type><br />
<file_location>TEST</file_location><br />
</document>
</document_list>
And this is the HTML i am using. There's a button and the <ul> tags i'm using;
<button onclick = "viewXMLFiles(); document.getElementById('showDocumentLink').style.display = 'block';">View Document Info</button><br>
<div id = "doclist">
<h2>Document 1;</h2>
<label>Document Name;</label><br><span id = "docname"></span><br>
<label>File Type</label><br><span id = "filetype"></span><br>
<label>File Location</label><br><span id = "fileloc"></span><br>
</div>
<div id = "doclist">
<h2>Document 2;</h2>
<label>Document Name;</label><br><span id = "docname1"></span><br>
<label>File Type</label><br><span id = "filetype1"></span><br>
<label>File Location</label><br><span id = "fileloc1"></span><br>
</div>
Can anyone help me put this into a loop? I have linked jQuery and jQTouch so i can use both of them.
Thank you so much in advance xx
Use following loop code.
<script>
xmlDoc = $.parseXML( xml ),
$xml = $( xmlDoc );
var documents = $xml.find('document_list');
documents.children('document').each(function() {
var name = $(this).find('document_name').text();
var file_type = $(this).find('file_type').text();
var file_location = $(this).find('file_location').text();
// now do whatever you like with above variable
});
</script>
Using Irfan's answer as a base, to get the values into your labels add a counter, then just insert the values grabbed from the XML parsing loop into the corresponding span.
<script>
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", "TestInfo.xml", false);
xmlhttp.send();
xmlDoc = xmlhttp.responseXML;
$xml = $( xmlDoc );
var documents = $xml.find('document_list');
var doccount = 0;
//will be used to find the HTML elements
var namelabel = "docname";
var typelabel = "filetype";
var locationlabel = "fileloc";
documents.children('document').each(function() {
var name = $(this).find('document_name').text();
var file_type = $(this).find('file_type').text();
var file_location = $(this).find('file_location').text();
//after the first document we need to add the number to the span id
if(doccount > 0){
namelabel = "docname" + doccount;
typelabel = "filetype" + doccount;
locationlabel = "fileloc" + doccount;
}
//insert the XML values into the label
$('span#'+namelabel).html(name);
$('span#'+typelabel).html(file_type);
$('span#'+locationlabel).html(file_location);
//increment the counter
doccount++;
});
</script>
Here is a native JavaScript implementation so you can see how you'd do it that way and compare, etc.
function viewXMLFiles() {
// var everything
var xmlhttp = new XMLHttpRequest(),
xmlDoc,
nodes, i, j, counter = -1, suffix,
document_name, file_type, file_location;
// request page
xmlhttp.open("GET", "TestInfo.xml", false),
xmlhttp.send();
// false meant synchronous req. so can go straight to reading document
xmlDoc = xmlhttp.responseXML;
// loop over <document> nodes
nodes = xmlDoc.childNodes; // shorthand
j = nodes.length;
for (i = 0; i < j; ++i) {
if ('document' === nodes[i].tagName.toLowerCase()) {
// nodes[i] is a <document>, increment counter
++counter;
// get nodes of intrest
document_name = nodes[i].getElementsByTagName("document_name")[0];
file_type = nodes[i].getElementsByTagName("file_type")[0];
file_location = nodes[i].getElementsByTagName("file_location")[0];
// do what you want with these, e.g.
suffix = counter || ''; // don't append a number for 0
document.getElementById('docname'+suffix).textContent = document_name.textContent;
document.getElementById('filetype'+suffix).textContent = file_type.textContent;
document.getElementById('fileloc'+suffix).textContent = pathToRoot + "/" + file_location.textContent;
}
}
}
Furthermore, you should consider the validity of your HTML, as I mentioned in my comment;
there should be no spaces around the equals sign of an attribute name/value pair, i.e. <tag attrib="val"/> not <tag attrib = "val"/>
every id attribute should have a unique value, not shared with any other on the document, i.e. not <tag id="shared"/><tag id="shared"/>

Categories

Resources