I have an application that uses Javascript to parses a XML array that is returned from a Webservice and iterates through it and builds it into a table body. It has been working with no issues until lately.
We had some changes on the database that the Webservice is returning results from in which now there are a few columns that could potentially have blanks or null values.
The Javascript fails to run when it hits a childNode that has a blank or null value.
Below is a snapshot of the browser error:
So my question is how do I handle those blanks so that the Javascript will just build an empty string into the table body and continue iterating through the xml array?
I have tried to build an if statement into the Javascript in the for loop to replace the blank or null value with '', but I'm not sure it's going to be doable with the way my table body is being built.
for (i = 0; i < x.length; i++) {
tbody += "<tr><td class=col1>" +
x[i].getElementsByTagName("CheckInDate")[0].childNodes[0].nodeValue +
"</td><td class=col2>" +
x[i].getElementsByTagName("CheckOutDate")[0].childNodes[0].nodeValue +
"</td><td class=col3>" +
x[i].getElementsByTagName("CheckInOut")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("address")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("names")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("companyName")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("Name")[0].childNodes[0].nodeValue.substr +
"</td><td>" +
x[i].getElementsByTagName("contactPhoneNum")[0].childNodes[0].nodeValue +
"</td ></tr >";
}
Being as how this is an existing application I don't want to rebuild all the functions that build tables using this method so I hope there is an easy solution to this that I'm not seeing.
The problem is that .childNodes will be null if the XML element doesn't have any content (any text nodes). You seem to have a lot of repeating code, to fix this you can create a function to get the content of an XML node with a specific tag name if it has any content or return an empty string.
Here is an example:
function getElementContent(element, tagName) {
const e = element.getElementsByTagName(tagName);
if (e && e.childNodes && e.childNodes.length) {
return e[0].childNodes[0].nodeValue
}
return '';
}
const tbody = x.map(e => `<tr><td class=col1>${getElementContent(e, 'CheckInDate')}</td><td class=col2>${getElementContent(e, 'CheckInDate')}..... `).join('');
Related
this is my first post so bare with me please.
We are currently working on our first Web-Project and have our problems finding the issues within our project. The project we are working on is a simple website for students to see which groups and modules they have joined. One example for a page is the group-overview which display one group with its members and some other data. The content of the member-table should be filled dynamically based on the group you currently selected. We tried to get this information within the function to fill the table by simply calling "request.query" but the received object is empty.
I´ll leave the code below. Sorry in advance if I have missed any necessary information - feel free to contact me.
Client-Side Fetch:
fetch('/getStudentsIntoTable')
.then (response =>
{
console.log(response);
return response.text();
}).then (text =>
{
document.getElementById("tableStudentGroup").innerHTML = text;
})
Server-Side Get-Request:
app.get("/getStudentsIntoTable", (request, response, next) => {
console.log(request.query); <!-- This hands back "{}" -->
let userID = request.session.userId;
let abfrage = "SELECT * FROM User ORDER BY 'Nachname'";
connection.query(abfrage, function(err, result, fields)
{
if (err) response.send("Es konnten keine Daten abgerufen werden.");
if (result != null)
{
var resultString = "";
for (var i = 0; i < result.length; i++)
{
resultString += "<tr><td>" + result[i].User_ID + "</td>" + "<td>" + result[i].Vorname + " " + result[i].Nachname + "</td>" + "<td>" + result[i].E_Mail + "</td></tr>";
}
response.send(resultString);
}
});
});
The URL Looks like this:
"http://localhost:3000/Gruppe/?Gravelshipping++"
The structure of a query string is a ? followed by a series of key=value pairs, separated by & characters (and with the keys and values URL encoded).
For example:
?name1=value1&name2=value2
Your URL doesn't follow that format.
I have this code:
compareList[productName] = productID + ',' + productHref;
console.log(productName + ' ' + productID + ' ' + productHref + ' ' + compareList.length);
Which logs into this (I have removed the link):
Acer Iconia B1-790 [NT.LDFEE.002] 112576 link removed for confidentiality 0
As you can see, all three variables are valid strings, but the json object still fails to assign (compareList.length logs as 0). I've been thinking and thinking but I simply can't figure it out. Any help is appreciated.
Maybe this version of adding and checking array length can be useful to you?
var compareList=[]
var productName = {productID:'saban',productHref:'http://saulic.com'};
compareList.push(productName);
console.log(compareList.length);
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
For some reason I have to use JSON like this:
php code
$json = json_decode([{
"key":1812,
"ticks":0,
"events":"7F7E7F7E7F7E7F7E7F7E7F7E7F7E",
"s1a":"011A00002066C0D9",
"s1c":"011C0149040901496650002830000000000000023344000043410000000300000004C5BD",
"s46":"014600283000CA8D","s10":"011000287182943B",
"s9a":"019A0000000018000000000000000000DC69",
"version" : "18.05"
}]);
// and use $json in loop to populate the table...
that pair of square brackets does not let me do anything with it in php. My editor show an parse error. I solved this problem in js like this:
var data = json[0];
var i;
for(i=0; i<json.length; i++){
var html = '';
html += '<td>' + json[i]["key"] + '</td>'
+ '<td>' + json[i]["ticks"] + '</td>'
+ '<td>' + json[i]["events"] + '</td>'
+ '<td>' + json[i]["s1a"] + '</td>'
+ '<td>' + json[i]["s1c"] + '</td>'
+ '<td>' + json[i]["s46"] + '</td>'
+ '<td>' + json[i]["s9a"] + '</td>'
+ '<td>' + json[i]["version"] + '</td>';
}
$(html).appendTo('#bundle');
//var jsonEncoded = JSON.parse(data);
console.log(json.length);*/
But it seems bad to use it like this. How can I solve this in php?
you can simply use json_decode for this in PHP, Like:
<?php
$data = json_decode($json);
var_dump($data[0]->key);
var_dump($data[0]->events);
And you can access them simply by using the index 0. Demo
Edit: The problem with your code is that your are not enclosing the json string in quotations. You should use it like this:
$json = json_decode('[{
"key":1812,
"ticks":0,
"events":"7F7E7F7E7F7E7F7E7F7E7F7E7F7E",
"s1a":"011A00002066C0D9",
"s1c":"011C0149040901496650002830000000000000023344000043410000000300000004C5BD",
"s46":"014600283000CA8D","s10":"011000287182943B",
"s9a":"019A0000000018000000000000000000DC69",
"version" : "18.05"
}]');
Also worth mentioning that if you are using an ORM, and you are working with collections (which is a common use case with Laravel, for example, and with many other PHP frameworks), there are two ways you can return something that you are looking for in a query.
First: you query an array of elements, and in this case, only one is found. Then, if you pass that as your response, it will contain the array brackets - a valid JSON type.
But if you specifically query for a single element (like with ::first() in the case of Eloquent), if you return that, it will automatically only return the object, without any enclosing brackets.
Edit: seeing your edit, yeah, mega6382 has the answer.
I am stuck with an annoying problem. I have an application on Google App Engine which sends some data (formatted as JSON string) from JS through POST to a php page. But when I select more than a specific amount of data, simply nothing is returned. I already tried to increase post_max_size to 20M, but not better. So where could be a limitation here? Is there another possibility to get data from JS to PHP? I tried like this:
function openWindowWithPost(url, name, keys, values) {
var newWindow = window.open(url, name);
if (!newWindow)
return false;
var html = "";
html += "<html><head></head><body><form id='formid' method='post' action='"
+ url + "'>";
if (keys && values && (keys.length == values.length))
for (var i = 0; i < keys.length; i++)
html += "<input type='hidden' name='" + keys[i] + "' value='"
+ values[i] + "'/>";
html += "</form><script type='text/javascript'>document.getElementById(\"formid\").submit()</sc"
+ "ript></body></html>";
newWindow.document.write(html);
return newWindow;
}
You could possibly check the server configuration file php.ini and check for the maximum post size max_post_size. If the default post string length isn't enough, you could increase it's length.
If you POST those big files, maybe you should check your upload_max_filesize-setting too.
Another possibility: Is your big JSON-File valid? You might try this here:
http://jsonlint.com/
You're likely hitting the 32 MB limit per request. To get around that, you'll need to Upload to GCS instead.
I am saving table data to a json object. The table data is coming from txt inputs and textareas in the table cells.
I'm running into a problem with CR/LF characters in the JSON elements holding the textarea data. The JSON data gets saved to the database fine, but when I pass it back to the jQuery function that populates the table using that data, I get this:
SyntaxError: JSON.parse: bad control character in string literal at line 1 column 67 of the JSON data
var array = JSON.parse(notes),
in the console.
I put the JSON data in Notepad++ with Show All Characters on and the CR/LF was at column 67.
Here's a sample of JSON data that I'm working with:
[["","","",""],["","9/23/14","",""],["","30789 detail, x_vendor_no**CR/LF HERE**
20597 header","",""],["","99 del invalid x_vendor_no","",""],["","30780","",""],["","","",""],["","","",""],["","","",""]]
Is there a way to allow CR/LF in the data?
UPDATE
11684's suggestion to use replace to remove the \r part of the CRLF won't work. Here's why:
Here's the complete function that uses the JSON data:
(Updated to work with Update #2 code below)
function PopulateTaskTableWithNotes(tableID,notesArray) {
// JSON parse removed per answer suggestion
var r, c, note;
for (r = 0; r < notesArray.length; ++r) {
for (c = 0; c < notesArray[r].length; ++c) {
note = notesArray[r][c];
$('#' + tableID + ' tr:nth-child(' + (r + 1) + ') td:nth-child(' + (c + 1) + ')').children(':first-child').val(note);
}
}
}
I still get the error on the line that tries to parse the JSON data. The replace function apparently can't "find" characters within an array element.
UPDATE #2
Here's how I am creating the array:
var siteID = $('#ddlUserSites option:selected').val(),
numRows = $('#' + tableID + ' tr').length,
numCols = $('#' + tableID).find('tr:first th').length,
notesArray = new Array(numRows),
rowNum = 1,
note = '',
colNum;
while (rowNum <= numRows) {
notesArray[rowNum] = new Array(numCols);
// Reset colNum for next row iteration
colNum = 1;
while (colNum <= numCols) {
note = '';
if ($('#' + tableID + ' tr:nth-child(' + rowNum + ') td:nth-child(' + colNum + ')').children(':first-child').is('input,textarea')) {
note = $('#' + tableID + ' tr:nth-child(' + rowNum + ') td:nth-child(' + colNum + ')').children(':first-child').val();
}
notesArray[rowNum][colNum] = note;
//console.log('Note for rowNum ' + rowNum + ', colNum ' + colNum + ': ' + note);
colNum++;
}
// Remove first element in current row array
notesArray[rowNum].shift();
rowNum++;
}
// Remove first element in array
notesArray.shift();
JSON.stringify(notesArray); // Added per an answer here
console.log('Final notesArray: ' + $.toJSON(notesArray));
$.ajax({
data: {saveTaskNotes: 'true', userID:userID, siteID:siteID, taskTable:tableID, notes:notesArray},
success: function(data) {
console.log('Save task notes data: ' + data);
}
});
The "Final notesArray" console output looks fine, but now, with stringify added, the function above (PopulateTaskTableWithNotes) console output shows that it's reading through every character in the array as a separate element!
Maybe this will help too, as far as what's happening to the data between the creating and reading functions: the array is being saved to a single MySQL database field and then retrieved for the PopulateTable function via $.ajax() (on both ends).
Having said that, do I need to look at what I'm doing with/to the array in the PHP code?
UPDATE #3
Here's the PHP function that takes the data in and writes to the MySQL db:
function SaveTaskNotes($userID,$siteID,$taskTable,$notes) {
$notes = json_encode($notes);
$insertUpdateTaskNotesResult = '';
$insertTaskNotes = "INSERT INTO userProgress (userProgressUserID,userProgressSiteID,userProgressNotesTable,userProgressNotes) values ($userID,$siteID,'" . $taskTable . "','" . $notes . "')";
$log->lwrite('$insertTaskNotes: ' . $insertTaskNotes);
$resultInsertTaskNotes = #mysqli_query($dbc,$insertTaskNotes);
if ($resultInsertTaskNotes) {
$insertUpdateTaskNotesResult = 'insertTaskNotesSuccess';
} else {
if (mysqli_error($dbc) != '') {
$log->lwrite('INSERT TASK NOTES: An error occurred while attempting to add the task notes. Query: ' . $insertTaskNotes . ', mysqli_error: ' . mysqli_error($dbc));
}
$insertUpdateTaskNotesResult = 'insertTaskNotesFail';
}
echo $insertUpdateTaskNotesResult;
}
And here's the function that gets the data from the db and sends it to the above $.ajax function:
function GetUserTaskNotes($userID,$siteID,$taskTableID) {
$queryGetUserTaskNotes = "SELECT userProgressNotes FROM userProgress WHERE userProgressUserID = $userID AND userProgressSiteID = $siteID AND userProgressNotesTable = '" . $taskTableID . "'";
$log->lwrite('$queryGetUserTaskNotes: ' . $queryGetUserTaskNotes);
$resultGetUserTaskNotes = #mysqli_query($dbc,$queryGetUserTaskNotes);
if ($resultGetUserTaskNotes) {
$taskNotes = mysqli_fetch_assoc($resultGetUserTaskNotes);
$log->lwrite('Retrieved $taskNotes[\'userProgressNotes\']: ' . $taskNotes['userProgressNotes']);
echo $taskNotes['userProgressNotes'];
} else {
if (mysqli_error($dbc) != '') {
$log->lwrite('GET TASK NOTES: An error occurred while attempting to retrieve the task notes. Query: ' . $queryGetUserTaskNotes . ', mysqli_error: ' . mysqli_error($dbc));
}
echo 'getTaskNotesFail';
}
}
In both the save and get functions the $log output shows that the array never changes (with the above js/php code) and pasting the array in to notepad++ shows that the CR/LF is still there throughout.
Don't use JSON.parse, the data is already JSON and Javascript can work with it.
You only need it when passing a string, imagine JSON.parse() beeing like string2json().
I think this might already be a solution to your problem, I've never had issues with new line characters.
As Luis said, the problem is not your client (Javascript, jQuery), besides the JSON.parse, but the providing site is wrong.
Example for PHP:
<?php
echo json_encode(array("test" => "
x"));
PHP properly escapes the characters:
{"test":"\r\n\r\n\r\nx"}
But the source of your data is providing malformed JSON.
To fix the JSON issue, either use prepared statements or use:
$notes = str_replace('\', '\\', json_encode($notes)); // in SaveTaskNotes
Well, the error is on the input data (showed in question). You can't have an CR or LF inside a literal in a JSON string. What you can have are that chars escaped as \r \n. The problem is on other side, where escaped codes are replaced by actual chars and therefore the full JSON string becomes invalid.