Displaying content of xml data in html file is not working - javascript

I want to display the content of a XML file into a html file.
I have seen and tried the example shown in the following link
https://www.youtube.com/watch?v=VxKGVb0oOBw
I have created html file copying the exactly the code in that example. Here is the code of my first html file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset=""UTF-8>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Test 1oading xml</title>
</head>
<body>
<div id='content'>
<table id="books" cellpadding="10px" style="text-align:left;">
<thead>
<tr><th>Author</th><th>Title</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<script>
let xmlContent = '';
let tableBooks = document.getElementById('books');
fetch('books.xml').then((response)=>{
response.text().then((xml)=>{
xmlContent = xml;
let parser = new DOMParser();
let xmlDOM = parser.parseFromString(xmlContent, 'appliction/xml');
let books = xmlDOM.querySelectorAll('book');
books.forEach(bookXmlNode => {
let row = document.createElement('tr');
//author
let td = document.createElement('td');
td.innerText = bookXmlNode.children[0].innerHTML;
row.appendChild(td);
//title
let td = document.createElement('td');
td.innerText = bookXmlNode.children[1].innerHTML;
row.appendChild(td);
tableBooks.children[1].appendChild(row);
});
});
});
</script>
</body>
</html>
copied the xml file content from here https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms762271(v%3Dvs.85) .. saved the file as books.xml in the same folder of the html file. Although Ideally I want to display data from external xml file so that the data can be updated dynamically.
When I open the html file it is not showing the xml data.
I have also tried with the code from this link.
https://www.encodedna.com/2014/07/extract-data-from-an-xml-file-using-javascript.htm
Thant is also not working.
How to display data of an (external) xml file into a html file
Screenshot of inspect page. The top one for the code of the you tube video.
The botom one is for the code from https://www.encodedna.com/2014/07/extract-data-from-an-xml-file-using-javascript.htm

Your code is basically correct but you have a few typos. Try the code below, which works for me. As other commenters have mentioned, you can't just open the file, you need a web server to serve it up. The video you link to does this using Live Server in Visual Studio Code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="" UTF-8>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Test 1oading xml</title>
</head>
<body>
<div id='content'>
<table id="books" cellpadding="10px" style="text-align:left;">
<thead>
<tr>
<th>Author</th>
<th>Title</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<script>
let xmlContent = '';
let tableBooks = document.getElementById('books');
fetch('books.xml').then((response) => {
response.text().then((xml) => {
xmlContent = xml;
let parser = new DOMParser();
let xmlDOM = parser.parseFromString(xmlContent, 'application/xml');
let books = xmlDOM.querySelectorAll('book');
books.forEach(bookXmlNode => {
let row = document.createElement('tr');
//author
let td = document.createElement('td');
td.innerText = bookXmlNode.children[0].innerHTML;
row.appendChild(td);
//title
let td2 = document.createElement('td');
td2.innerText = bookXmlNode.children[1].innerHTML;
row.appendChild(td2);
tableBooks.children[1].appendChild(row);
});
});
});
</script>
</body>
</html>
The typos are: id="books", 'application/xml' and you can't use td as a variable name twice.
By the way, when you have problems like this the first place to look is in the browser's console window. Hit F12 after the browser has launched and failed to show your data, and go to Console if it's not selected: it will show you any errors and where they are coming from. If you're using VS Code you can actually debug the script as well I think, meaning you can single-step through it seeing what's going on.

Related

JS ReferenceError: getActivityTables is not defined at onload [duplicate]

This question already has answers here:
How to run a function when the page is loaded?
(11 answers)
Closed 2 months ago.
Why is getActivityTables() not defined? The script is properly linked, and the function name is the same in the html as well as js file.
What am I doing wrong?
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Fitnessapp</title>
<script src="scripts.js"></script>
</head>
<body onload="getActivityTables()">
<div id="" class="container">
<div class="activityDiv">
<h1>Running Activities</h1>
<table id="runningActivity-table" class="table">
</table>
</div>
</div>
</body>
</html>
JS (scripts.js):
function getActivityTables() {
console.log("test");
// Get runningActivity-table
let xhttp = new XMLHttpRequest();
xhttp.onload = function () {
let response;
let responseString = xhttp.responseText;
response = JSON.parse(responseString);
console.log(response);
let table = document.getElementById("runningActivity-table");
let row, cell;
let header = table.createTHead();
row = header.insertRow(0);
cell = row.insertCell();
cell.innerHTML = "ID";
cell = row.insertCell();
cell.innerHTML = "Date";
cell = row.insertCell();
cell.innerHTML = "Duration";
cell = row.insertCell();
cell.innerHTML = "Distance";
cell = row.insertCell();
cell.innerHTML = "Description";
for (let i = 0; i < response.length; i++) {
row = table.insertRow();
cell = row.insertCell();
cell.textContent = response[i].id;
cell = row.insertCell();
cell.textContent = response[i].dateOfCreation;
cell = row.insertCell();
cell.textContent = response[i].durationInMinutes;
cell = row.insertCell();
cell.textContent = response[i].distanceInKm;
cell = row.insertCell();
cell.textContent = response[i].description;
}
}
xhttp.open("GET", "/getRunningActivities");
xhttp.send();
}
I cannot find the problem. I have the exact same code for another page and thats working properly.
I copied your entire code exactly in my vs code, and launched it, and everything is working.
The getActivityTables function worked fine.
But you can try to use the addEventListener() inside the javascript itself, it's better than the regular html events attributes.
But your code doesn't have any problems, I tried it myself.
You can capture the console and the network tab in your browser then we can figure out what's happened.
try to remove <script src="scripts.js"></script> from the head tag And put it at the end of the Body tag
like this :
<body onload="getActivityTables()">
<div id="" class="container">
<div class="activityDiv">
<h1>Running Activities</h1>
<table id="runningActivity-table" class="table">
</table>
</div>
</div>
<script src="scripts.js"></script>
</body>
if problem still
in scripts.js file add :
window.addEventListener('load',getActivityTables())

javascript array is being read before creating items

I have created a section including all its content using JS.
const main = document.querySelector('main') ,
new_p = document.createElement('p'),
new_h2 = document.createElement('h2'),
new_div = document.createElement('div'),
new_section = document.createElement('section')
main.appendChild(new_section);
new_section.id = ('section4');
new_section.appendChild(new_div);
new_div.classList.add('landing__container');
new_div.appendChild(new_h2);
new_div.appendChild(new_p);
new_h2.textContent = 'Section 4';
new_h2.id = 'heading4';
new_p.textContent = 'some text goes here'
Then I made an array of all sections (previously created using HTML and newly created using JS).
const sections = Array.from(document.getElementsByTagName("section"))
The problem is that array gets only the sections created with HTML only and can't see the ones created with JS.
here is the array logged to the console (the 3 items in the array are already created with HTML)
(3) [section#section1.your-active-class, section#section2, section#section3]
Anyone can help me how to detect newly created sections with JS?
I tested this code and it's working. JS has no problems here. Maybe you are trying to access sections before the new one is added.
See this snippet:
const main = document.querySelector('main') ,
new_p = document.createElement('p'),
new_h2 = document.createElement('h2'),
new_div = document.createElement('div'),
new_section = document.createElement('section')
main.appendChild(new_section);
new_section.id = ('section4');
new_section.appendChild(new_div);
new_div.classList.add('landing__container');
new_div.appendChild(new_h2);
new_div.appendChild(new_p);
new_h2.textContent = 'Section 4';
new_h2.id = 'heading4';
new_p.textContent = 'some text goes here'
const sections = Array.from(document.getElementsByTagName("section"))
console.log(sections);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- <script type="module" src="./async-await.js"></script> -->
<script type="module" src="./script.js" defer></script>
</head>
<body>
<main>
<section id="section1"></section>
<section id="section2"></section>
<section id="section3"></section>
</main>
</body>
</html>

How to create table in Node.js script using data from a file?

Node.js script contains following route definition:
app.get('/',function(req,res){
res.writeHead(200,{'Content-Type': 'text/html'});
fs.createReadStream('file.txt').pipe(csv()).on('data',(data)=>result.push(data)).on('end',() =>{
.
.
.
.
let param1 = first;
let param2 = second;
let param3 = third;
let param4 = forth;
.
.
.
res.write(html_table); // the task
res.end();
});
})
Variables param? represent the data extracted from a file necessary for the table. Goal is to make this route return response which will contain html document with a table (or just a table). Let
param1 = "First parameter", param2 = "Second parameter"...
The response should be in following format.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script></script>
<title>Table</title>
</head>
<body>
<table id="myTable" border="1px solid black">
<tr>
<th>Param1</th>
<th>Param2</th>
<th>Param3</th>
<th>Param4</th>
</tr>
<tr>
<td>First parameter</td>
<td>Second parameter</td>
<td>Third parameter</td>
<td>Forth parameter</td>
</tr>
</table>
</body>
</html>
What is the best approach for solving this? Is it using cheerio package, or manipulating with client and server side javascript files?
First you need to create a HTML file in your project folder. I created mine as table.html in directory projectFolder/files/. So the HTML file should look like this:
projectFolder/files/table.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<table>#{tableData}</table>
</body>
</html>
Notice that in our table.html we have #{tableData} text written inside table element. We will replace this #{tableData} text with our redered HTML in the router.
Next step is manipulating this HTML file in your router and send it to the client. To do this, we need file system module.
router.get('/', function(req, res, next) {
// Read HTML file
fs.readFile('./files/table.html', 'utf-8', function(err, data) {
// Redirect to error handler if there's any error
if(err) return next(err);
res.writeHead(200, { 'Content-Type': 'text/html' });
let tableData = {
param1: 'value1',
param2: 'value2',
param3: 'value3'
};
// Write tableData object as a HTML table rows and columns
let tableDataHead = '<tr>';
let tableDataBody = '<tr>';
for(let param in tableData) {
tableDataHead += `<th>${param}</th>`;
tableDataBody += `<td>${tableData[param]}</td>`;
}
tableDataHead += '</tr>';
tableDataBody += '</tr>';
// Concatenate tableDataHead and tableDataBody
let tableDataHTML = tableDataHead + tableDataBody;
// Replace #{tableData} text with our HTML data
data = data.replace('#{tableData}', tableDataHTML);
// Send rendered HTML file to the client
res.write(data);
res.end();
});
});
And the final response sended to client should look like this:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body cz-shortcut-listen="true">
<table>
<tr>
<th>param1</th>
<th>param2</th>
<th>param3</th>
</tr>
<tr>
<td>value1</td>
<td>value2</td>
<td>value3</td>
</tr>
</table>
</body>
</html>
Well the question includes a lot of code so I will give you a short set of steps that can help.
You need to read the file and save into a variable (Looks like you already doing that);
Now you need to use some kind of template engine to render the HTML page. I would advise you to use EJS, as a template engine.
Assuming that you have created an EJS template called csv-table.ejs file you need to call render function to render the data you have.
Let's say you have an array data variable, and you are using a template that is using data variable too, so you need to call response.render('csv-table', { data });
In the template you will need to loop over the data variable and render the table.

Routing(?) in Vanilla JS

I need my webite to display info in a certain language, based on a query in my webite's URL (e.g. www.website.com/index.php?country=FR). How can I do that with vanilla JS and not React/Angular?
My approach:
1) JS recognizes a query in the URL (in this case- 'country=FR') and then appends a js file, which has neccessary french words in it defined by variables.
2) JS in my script tag that's in the HTML file, appends the main page markup text with template literals in it.
3)
I don't know, whether the browser fails to either fetch the language file itself or its variables. At the moment it does not render anything.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="./js/main.js"></script>
</head>
<body>
<script>
const template= `
<h1>Good Morning: ${goodmorning} </h1>
<h2>Good Evening: ${goodevening} </h2>
<h3>My name is: ${mynameis}</h3>`
function markupAppend() {
$('body').html(template);
console.log('Markup loaded')
}
markupAppend()
</script>
</body>
</html>
=========================
Main.js
var domain = window.location.href;
var FRString = domain.includes("country=FR");
var ESString = domain.includes("country=ES");
if (FRString) {
$('head').append(`<script src="./Language_files/FRENCHwords.js" />`)
}
if (ESString) {
$('head').append(`<script src="./Language_files/SPANISHwords.js" />`)
}
=========================
FRENCHwords.js
const goodmorning = 'Bonjour';
const goodevening = 'Bonsoir';
const mynameis = 'Mon nom est';
=========================
SPANISHwords.js
const goodmorning = 'Buenos dias';
const goodevening = 'Buenas tardes';
const mynameis = 'Mi nombre es';
No errors displayed, the page is just not rendering...
In Your main.js file, you are using domain.includes, it only returns the domain name but not the entire URL. You can use window.location.href.includes for this.
Instead of: domain.includes("country=FR");
Try: window.location.href.includes("country=FR");

parse table row with cheerio

I try to extract some data from a table with cheerio.
Here is a simplified version:
const table = `
<table>
<tr>
<td></td>
<td class="with-link"></td>
</tr>
</table>
`
const row = `<td></td>`
class Scraper {
htmlToDom(html) {
return cheerio.load(html)
}
findHref(row) {
return row('a').attr('href')
}
}
const scraper = new Scraper()
const cheerioRow = scraper.htmlToDom(row)
console.log(scraper.findHref(cheerioRow))
const cheerioTable = scraper.htmlToDom(table)
cheerioTable('tr').each(function() {
//console.log(this)
let td = this.find('td.with-link')
console.log(scraper.findHref(td))
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<script src="https://wzrd.in/standalone/cheerio#latest"></script>
<title>JS Bin</title>
</head>
<body>
</body>
</html>
Scraper class has two methods, one can load the html (string) and returns a cheerio object. The other one expects a (cheerio) td object, and returns the href from it.
The first console log shows that findHref works as expected. Then I load a whole table, loop through its rows (just one in this case). Inside the each loop this should be a roe (tr) object. I try to find the correct cell (with class 'with-link'), and pass it to findHref.
But I am getting
"TypeError: this.find is not a function
Just in case, here is the JsBin: https://jsbin.com/vakofapiro/edit?js,console
Instead of this use cheerioTable.
`let td = cheerioTable(this).find('td.with-link').html();`
It will give you the inner html of td which is a href

Categories