Parsing nested XML response in Jquery Ajax - javascript

I am writing a asp.net web api web service. Along with the service I am also writing a tester so the web service can be tested.
the tester allows you to post and receive either JSON or XML. I am processing the response using jquery ajax. I am fine using JSON and the below works fine.
the JSON response
{"ItemLabel":
{"Requisition":"W44DQ18255TS42 ",
"Nsn":"5999-01-100-5901",
"FscNiin":"5999011005901 ",
"Cage":"1CAY9",
"PartNumber":"",
"Nomen":"CONTACT,ELECTRICAL ",
"Quantity":"1",
"Ui":"EA",
"UiDesc":"",
"PurchOrderNbr":"SPM907-85-5-4444",
"RlseNbr":"TS0042",
"Clin":"0042 ",
"Lot":"",
"Preservation":"",
"DatePreserved":"",
"ShelfType":"",
"Shelf1":"",
"Exp1":"",
"CureDt1":"",
"CureInsp1":"",
"Shelf2":"",
"Exp2":"",
"CureDt2":"",
"CureInsp2":"",
"Serials":"",
"Serial":null,
"SerialInters":null,
"UnitPerInt":"1",
"TypeLbl":"ITEMx1"
},
"filePaths":["https://xxxxxxxxxxx.dir.ad.dla.mil/pdf/email_ITEMLBL__W44DQ18255TS42 _682895.pdf"]
}
and I can process the results using jquery ajax as follows.
success: function (result) {
$('#Spinner129').hide();
self.jsonResponse129(JSON.stringify(result));
self.hasSuccess129(true);
self.successMessage129("Success! Please view the response in the JSON Response tab below.");
$.each(result.filePaths, function (i, path) {
window.open(path, '_blank');
});
},
although I am struggling a bit to do the same thing with the xml response how do I get the values in filepaths?
here is the xml response
<FobOriginWebService129PLabelOutput xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/VSM">
<ItemLabel>
<Cage>1CAY9</Cage>
<Clin>0042 </Clin>
<CureDt1></CureDt1>
<CureDt2></CureDt2>
<CureInsp1></CureInsp1>
<CureInsp2></CureInsp2>
<DatePreserved></DatePreserved>
<Exp1></Exp1>
<Exp2></Exp2>
<FscNiin>5999011005901 </FscNiin>
<Lot></Lot>
<Nomen>CONTACT,ELECTRICAL </Nomen>
<Nsn>5999-01-100-5901</Nsn>
<PartNumber i:nil="true" />
<Preservation></Preservation>
<PurchOrderNbr>SPM907-85-5-4444</PurchOrderNbr>
<Quantity>1</Quantity>
<Requisition>W44DQ18255TS42 </Requisition>
<RlseNbr>TS0042</RlseNbr>
<Serial i:nil="true" />
<SerialInters i:nil="true" />
<Serials></Serials>
<Shelf1></Shelf1>
<Shelf2></Shelf2>
<ShelfType>SHL0</ShelfType>
<TypeLbl>ITEMx1</TypeLbl>
<Ui>EA</Ui>
<UiDesc></UiDesc>
<UnitPerInt>1</UnitPerInt>
</ItemLabel>
<filePaths xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:string>https://xxxxxxxxxxx.dir.ad.dla.mil/pdf/email_ITEMLBL__W44DQ18255TS42 _405955.pdf</d2p1:string>
</filePaths>
</FobOriginWebService129PLabelOutput>
not sure how to process it in the jquery ajax success section here was my attempt.
success: function (result) {
$('#Spinner129').hide();
self.hasSuccess129(true);
self.successMessage129("Success! Please view the response in the XML Response tab below.");
self.xmlResponse129(JSON.stringify(result));
// xmlDoc = $.parseXML(result),
// $xml = $(xmlDoc),
// $filePath = $xml.find("filePaths");
// now what?
},

The file path is nested within the children of filePaths node.
<filePaths xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d2p1:string>https://xxxxxxxxxxx.dir.ad.dla.mil/pdf/email_ITEMLBL__W44DQ18255TS42 _405955.pdf</d2p1:string>
</filePaths>
Once you have $filePaths as following:
$filePaths = $xml.find("filePaths");
You can access its children and then get its text:
$filePaths.children().each(function () {
//console.log($(this).text()); // print to test
// https://xxxxxxxxxxx.dir.ad.dla.mil/pdf/email_ITEMLBL__W44DQ18255TS42 _405955.pdf
// open in new window
window.open($(this).text(), '_blank');
});

Everything looks fine. To get filePath value try this:
$filePath.text();

Related

PHP 'array() image' equivalent for javascript

I am trying to upload image to an Etsy listing via their API v2. Their documentation have code example of image upload in PHP, in which the POST request body parameter is given like this
$params = array('#image' => '#'.$source_file.';type='.$mimetype);
How would I go about replicating this in JavaScript? I have tried sending the image blob as the image parameter but it does not seem to be working.
Edit: I am using npm oauth package. Here is my complete code that I am using to call the API.
var oauth1 = new OAuth1.OAuth(
'https://openapi.etsy.com/v2/oauth/request_token?scope=email_r%20listings_r%20listings_w%20listings_d',
'https://openapi.etsy.com/v2/oauth/access_token',
'api_key',
'api_secret',
'1.0A',
null,
'HMAC-SHA1'
);
oauth1.post(
'https://openapi.etsy.com/v2/listings/915677000/images',
req.user.etsy.oauth_token,
req.user.etsy.oauth_token_secret,
{
'listing_id': 915677000,
'image': <image has to go here>
},
'multipart/form-data',
function (e, data, response){
if (e) console.error(e);
// let body = JSON.parse(data);
console.log(data);
res.redirect('/create-listings')
});

function fetch_images() from folder not api

I have a responsive-image-gallery- code in HTML5 that fetches an image from Filker. I want to fetch image from img folder and get the title automatically from the .jpg name this is the code
// fetch images from Flickr
function fetch_images() {
$.getJSON(api_flickr, {
tags: $("#searchinput").val(),
tagmode: "any",
format: "json"
})
.done(function(data) {
$.each(data.items, function(i, item) {
var url = item.media.m;
var title = item.title;
var elem = $("<div class='my show'><img src='"+url+"'/><div>"+
title+"</div>");
images.append(elem);
});
// add more-div and resize
images.append($("#morediv").clone().removeAttr("id"));
resize_images();
});
}
Flicker has an API that provides JavaScript with a JSON-formatted list of filenames.
In order for your script to do the same, you need to either provide it with the same type of API (maybe with a PHP script) or with a list of the filenames in the img folder.
References:
JSON - Learn what JSON is
PHP Script - Learn how to create a PHP script to output what you need

AJAX : What to do when the POST succeeds?

I've been doing a lot of searching the last few days on AJAX.
I see why I postponed learning that particular area of JavaScript, it seems a little complex.
I notice that most questions and answers are formulated around how to SEND data via POST, but I can't find any detailed examples of what to DO with the data once the POST has completed.
I want to use JavaScript rather than php to process the data server side, and I haven't found any useful Q/A. tutorials or discussion on the topic, excluding PHP. I figure I have to ask the specific question myself.
To help visualize my question I'll give the specific example that stimulates my question.
I have a file containing a list of tasks pending, and a list of tasks completed.
The functionality in this list is that when a user clicks on the task, it is inserted into a database, where it is associated with the user.
Multiple users see this page and anyone logged in can "log" a task completed by clicking on the list item. The list item also opens another page containing more details on the item and cascades to some other functions while logging the completion and user data to the database.
<h3>To Do!</h3>
<ol class="pending>
<li><a class="pending_task" href="localhost://nextstep.html">Task Three</a></li>
<li><a class="pending_task" href="localhost://nextstep.html">Task Five</a></li>
<li><a class="pending_task" href="localhost://nextstep.html">Task Six</a></li>
</ol>
On the same page is the "Completed" task list which is populated when the pending is clicked:
<h3>Completed!</h3>
<ol class="completed">
<li><a class="completed_task" href="localhost://nextstep.html">Task One</a></li>
<li><a class="completed_task" href="localhost://nextstep.html">Task Two</a></li>
<li><a class="completed_task" href="localhost://nextstep.html">Task Four</a></li>
</ol>
The code which manages that:
$(document).ready(function(){
$('.pending').on('click', function(){
evt.preventDefault();
$(this).toggleClass("pending").parent().appendTo("ol.completed");
});
});
My goal is to have the static html updated server side, when a task has been completed, so that when the page reloads or is accessed by another user, the new configuration of "Pending" vs "Completed", is current. As a friend explained, I can't just write the updated file to server from the client side, so I realized AJAX was the best solution. Send the updated information to the server and have a script on the server side rewrite the source file when a task has been clicked as complete. I have done the $_POST[key] functionality with PHP, but I have been more impressed with JavaScript so I want to learn how to do this purely in JavaScript.
Based on my new understanding, I changed the code a bit:
$(document).ready(function(){
$('.pending').on('click', function(){
evt.preventDefault();
$(this).toggleClass("pending").parent().appendTo("ol.completed");
var newData = $("ul.pending") + $("ul.completed");
console.log(newData);
var xhr = $.ajax({ //jshint ignore: line
method:'POST',
data: newData,
url:"update.js",
success: function(){
console.log("completed POST");
},
dataType: 'html',
}); //xhr
});
});
So I get this far and I'm confused by how to properly activate the receiving script so that the file is rewritten and also perhaps reload the file so that the persistence of the change is maintained.
I'm looking to understand the details of handling the POST data, without using PHP or a DATABASE. I just want to rewrite the HTML with the updated changes to the <ol> items.
If this is not the proper forum for that or there are resources that would help enlighten me, I would appreciate advice on how to find the best resources.
Thank You.
UPDATE:
I am using node.js on the server side. The HTML is being presented via an app.js so the idea of doing server side operations is deeply connected to using node.js
Update 2:
I'm a little lost in the process of the POST/response dynamic.
The script initiating the POST will get a response, of that I am clear.
So if I want the POSTEd html to be manipulated on the server side, then the response will come from the node.js indicating that the file has been rewritten, as requested by the POST? So the response can/will be a result of something I code on the server side.
My question remains though: How do I manipulate the POST data on the server side?
In PHP it is $_POST[key]. What is it in JavaScript?
And since I am sending HTML as the POST data, how should I handle it? Will it be a hash {key, value} or is it in some other form? I can't find these details in my google searching. I'm not sure how to phrase the question to get the answer I need.
And further, what triggers the node script to execute on the server side once it has been addressed y the POST call? Or am I overthinking that part?
You seem to misunderstand the server/client model. You cannot use html/javascript to change things in your server, for that you will have to use your PHP server.
You can have a javascript server with Node.js https://nodejs.org , but that will probably replace your current PHP server. You can have multiple server in different languages, but that will make your project a bit harder to maintain.
Now about the AJAX request, it's like any other http request. You will send a header with your meta data and you will receive the answer from the server. If you want the server to do something (like write to a file or DB) every time it receives an specific request, you will need to code that by yourself.
UPDATE
You edited your question, now I know you're using nodejs. Here are a few extra info that might help
1 - Take a look at this question (it's really basic stuff and might help a lot)
Basic Ajax send/receive with node.js
2 - Change this line:
var newData = $("ul.pending") + $("ul.completed");
to this:
var newData = $("ul.pending").html() + $("ul.completed").html();
3 - This question will show you how to handle POST in node How do you extract POST data in Node.js?
This was the final code I developed after coming to an understanding of AJAX:
http.createServer(function(req, res){
if ((req.method === 'POST') && (req.url === '/result')){
var body = '';
res.statusCode = 200;
res.end("Message Received!");
req.on('data', function(data){
body += data;
});
req.on('end', function () {
var suffix = getDateTime();
var output = "Links" + "_" + suffix + ".html";
// Copy the original First
fs.writeFileSync(output, fs.readFileSync("./Links.html"));
// Overwrite the original file with the updated list configuration
fs.writeFileSync("./Links.html", body, 'utf-8');
});
} else if (req.method === 'GET') { // Reorganized 2017 01 05 # 2237
// Serve the static html
var filename = req.url || "Links.html";
var ext = path.extname(filename);
var localPath = __dirname;
var validExtensions = {
".html": "text/html",
".css": "text/css",
".js": "application/javascript",
".txt": "text/plain",
".jpg": "image/jpeg",
".gif": "image/gif",
".png": "image/png",
".woff": "application/font-woff",
".woff2": "application/font-woff2",
".ico": "image/x-icon",
"" : "text/html"
};
var validMimeType = true;
var mimeType = validExtensions[ext];
if (checkMimeType){
validMimeType = validExtensions[ext] !== undefined;
}
if (validMimeType){
localPath += filename;
fs.exists(localPath, function(exists){
if (exists){
getFile(localPath, res, mimeType);
} else {
console.log("File not found: " + localPath);
res.writeHead(404);
res.end();
}
});
} else {
console.log("Invalid file extension detected: " + ext + "(" + filename + ")");
}
}
}).listen(port, serverURL);
function getFile(localPath, res, mimeType){
fs.readFile(localPath, function(err, contents){
if (!err) {
res.setHeader("Content-Length", contents.length);
if (mimeType !== undefined){
res.setHeader("Content-Type", mimeType);
}
res.statusCode = 200;
res.end(contents);
} else {
res.writeHead(500);
res.end();
}
});
}
The other relevant code:
/* jslint node: true, browser: true */ /* globals $:false */
"use strict";
var ajax_url ="/result";
$(document).ready(function(){
$('.source_link').on('click', function(){
//evt.preventDefault();
$(this).toggleClass("source_link downloaded").parent().appendTo("ol.downloaded");
var front = "<!doctype html><html>";
var head1 = "<head><link rel=\"stylesheet\" href=\"link.css\">";
var head2 = "<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js\"></script>";
var head3 = "<script src=\"links.js\"></script>";
var head4 = "<script src=\"nameanchor.js\"></script>";
var head5 = "</head><body>";
var bottom = "</body></html>";
var newData = front + head1 + head2 + head3 + head4 + head5 + "<ol class=\"pending\">" + $('ol.pending').html() +
"</ol>" + "<ol class=\"downloaded\">" + $('ol.downloaded').html() + "</ol>" + bottom;
$.ajax({
method:'POST',
data: newData,
url: ajax_url,
success: function(result, status, jqxhr){
console.log("Response: " + jqxhr.responseText);
console.log("POST status: " + status);
},
dataType: 'html',
});
});
});

Downloading files in Mojolicious

Simple question. I have a .doc file generated in my mojolicious app. I want to download it. That's my question, how do I get the browser to download it?
I'm using the CPAN module MsOffice::Word::HTML::Writer to generate the doc.
Here is the sub routine in my mojolicious app, it is called by an Ajax request in Jquery:
sub down_doc {
my $self = shift;
my $doc = MsOffice::Word::HTML::Writer->new(
title => "My new Doc",
WordDocument => {View => 'Print'},
);
$doc->write("Content and Stuff");
my $save = $doc->save_as("/docs/file.doc");
$self->res->headers->content_disposition("attachment;filename=file.doc");
$self->res->headers->content_type('application/msword');
$self->render(data => $doc->content);
}
Here is my Ajax request in Jquery:
var request = $.ajax({
url: "/down_doc",
type: "post",
data: {'data': data},
});
request.done(function(response, textStatus, jqXHR) {
window.location.href = response;
});
I know that my Ajax "done" handler is wrong, I was just experimenting. How do I make my webpage prompt to save and download the .doc file?
You where pretty close, but I would recommend either of the following options...
File Download Processing with Mojolicious
You can install the plugin Mojolicious::Plugin::RenderFile to make this easy.
Example
plugin 'RenderFile';
sub down_doc {
my $self = shift;
my $doc = MsOffice::Word::HTML::Writer->new(
title => "My new Doc",
WordDocument => {View => 'Print'},
);
$doc->write("Content and Stuff");
my $save = $doc->save_as("/docs/file.doc");
$self->render_file('filepath' => "/docs/file.doc");
}
Or if you want to only use Mojo the following will work, and is explained further at the link below.
use Cwd;
app->static->paths->[0] = getcwd;
sub down_doc {
my $self = shift;
my $doc = MsOffice::Word::HTML::Writer->new(
title => "My new Doc",
WordDocument => {View => 'Print'},
);
$doc->write("Content and Stuff");
my $save = $doc->save_as("/docs/file.doc");
shift->render_static("/docs/file.doc");
}
Reference
This really isn't a problem on the server side, but rather that you can't save the response from an ajax request without using the (relatively new) File API. I would suggest replacing the ajax with a temporary form:
$('<form method="post" action="/down_doc">')
.append(
$('<input type="hidden" name="data">')
.attr("value", JSON.stringify(data))
)
.appendTo('body')
.submit();
When form is submitted and your /down_doc handler replies with the appropriate content-disposition header and the document data, the browser will do the work of handling the file save.
If you're not planning to use the file on the server after the request, this line can be removed:
my $save = $doc->save_as("/docs/file.doc");

How to check if page exists using JavaScript

I have a link: Hello.
When someone clicks the link I'd like to check via JavaScript if the page the href-attribute points to exists or not. If the page exists the browser redirects to that page ("www.example.com" in this example) but if the page doesn't exist the browser should redirect to another URL.
It depends on whether the page exists on the same domain or not. If you're trying to determine if a page on an external domain exists, it won't work – browser security prevents cross-domain calls (the same-origin policy).
If it is on the same domain however, you can use jQuery like Buh Buh suggested. Although I'd recommend doing a HEAD-request instead of the GET-request the default $.ajax() method does – the $.ajax() method will download the entire page. Doing a HEAD request will only return the headers and indicate whether the page exists (response codes 200 - 299) or not (response codes 400 - 499). Example:
$.ajax({
type: 'HEAD',
url: 'http://yoursite.com/page.html',
success: function() {
// page exists
},
error: function() {
// page does not exist
}
});
See also: http://api.jquery.com/jQuery.ajax/
A pretty good work around is to proxy. If you don't have access to a server side you can use YQL. Visit: http://developer.yahoo.com/yql/console/
From there you can do something like: select * from htmlstring where url="http://google.com". You can use the "REST query" they have on that page as a starting point for your code.
Here's some code that would accept a full URL and use YQL to detect if that page exists:
function isURLReal(fullyQualifiedURL) {
var URL = encodeURIComponent(fullyQualifiedURL),
dfd = $.Deferred(),
checkURLPromise = $.getJSON('http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20htmlstring%20where%20url%3D%22' + URL + '%22&format=json');
checkURLPromise
.done(function(response) {
// results should be null if the page 404s or the domain doesn't work
if (response.query.results) {
dfd.resolve(true);
} else {
dfd.reject(false);
}
})
.fail(function() {
dfd.reject('failed');
});
return dfd.promise();
}
// usage
isURLReal('http://google.com')
.done(function(result) {
// yes, or request succeded
})
.fail(function(result) {
// no, or request failed
});
Update August 2nd, 2017
It looks like Yahoo deprecated "select * from html", although "select * from htmlstring" does work.
Based on the documentation for XMLHttpRequest:
function returnStatus(req, status) {
//console.log(req);
if(status == 200) {
console.log("The url is available");
// send an event
}
else {
console.log("The url returned status code " + status);
// send a different event
}
}
function fetchStatus(address) {
var client = new XMLHttpRequest();
client.onreadystatechange = function() {
// in case of network errors this might not give reliable results
if(this.readyState == 4)
returnStatus(this, this.status);
}
client.open("HEAD", address);
client.send();
}
fetchStatus("/");
This will however only work for URLs within the same domain as the current URL. Do you want to be able to ping external services? If so, you could create a simple script on the server which does your job for you, and use javascript to call it.
If it is in the same domain, you can make a head request with the xmlhttprequest object [ajax] and check the status code.
If it is in another domain, make an xmlhttprequest to the server and have it make the call to see if it is up.
why not just create a custom 404 handler on the web server? this is probably the more "good-bear" way to do this.
$.ajax({
url: "http://something/whatever.docx",
method: "HEAD",
statusCode: {
404: function () {
alert('not found');
},
200: function() {
alert("foundfile exists");
}
}
});
If you are happy to use jQuery you could do something like this.
When the page loads make an ajax call for each link. Then just replace the href of all the links which fail.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script type="text/javascript">
<!--
$.fn.checkPageExists = function(defaultUrl){
$.each(this, function(){
var $link = $(this);
$.ajax({
url: $link.attr("href"),
error: function(){
$link.attr("href", defaultUrl);
}
});
});
};
$(document).ready(function(){
$("a").checkPageExists("default.html");
});
//-->
</script>
You won't be able to use an ajax call to ping the website because of same-origin policy.
The best way to do it is to use an image and if you know the website you are calling has a favicon or some sort of icon to grab, you can just use an html image tag and use the onerror event.
Example:
function pingImgOnWebsite(url) {
var img = document.createElement('img');
img.style.visibility = 'hidden';
img.style.position = 'fixed';
img.src = url;
img.onerror = continueBtn; // What to do on error function
document.body.appendChild(img);
}
Another way to do this is is with PHP.
You could add
<?php
if (file_exists('/index.php'))
{
$url = '/index.php';
} else {
$url = '/notindex.php';
}
?>
And then
<a href="<?php echo $url; ?>Link</a>

Categories