Reputation: 75
I'm doing the W3 XML DOM tutorial. I can't understand why the iteration produces 1, 3, 5, 7 in the output. I understand everything else ( I think !) Can someone help to explain? Thanks.
<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myFunction(this);
}
};
xhttp.open("GET", "books.xml", true);
xhttp.send();
function myFunction(xml) {
var x, y, i, xlen, xmlDoc, txt;
xmlDoc = xml.responseXML;
x = xmlDoc.getElementsByTagName("book")[0];
xlen = x.childNodes.length;
y = x.firstChild;
txt = "";
for (i = 0; i < xlen; i++) {
if (y.nodeType == 1) {
txt += i + " " + y.nodeName + "<br>";
}
y = y.nextSibling;
}
document.getElementById("demo").innerHTML = txt;
}
</script>
</body>
</html>
Output is:
1 title
3 author
5 year
7 price
Hello Andy, here is the xml DOM file, It's from https://www.w3schools.com/xml/dom_nodes.asp
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="web">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
<book category="web" cover="paperback">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>
Additional comments in response to Carlos22's answer. I'm sorry Carlos, I still don't understand.
(y.nodeType ==1)
will always return true because the children of the first occurrence of <book>
are all of type element (nodeType = 1)
first loop i = 0
so value of txt should be 0 title
second loop i = 1
so 0 title
should concatenate with 1 author
so value of string txt is now 0 title 1 author
third loop i = 2
txt contains the string 0 title 1 author 2 year
and so on.
I am sometimes capable of being incredibly stupid, so please forgive !!
Upvotes: 0
Views: 708
Reputation: 75
With the help of Anton and Andy Meissner, I have learned and understood something very useful! Also after studying this source: [[What You Need to Know About Whitespace in XML]][1][1]
The behaviour of the code can be explained by how the parser treats white space in XML DOM
in the following XML DOM:
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
It would be tempting to think that the element node <book>
has four children, namely four elements <title>, <author>, <year> and <price>
but in fact it has 7 children because the parser treats the white space (carriage return + line feed) after each element node as an empty text node.
So, as Anton demonstrated the element actually has 7 children:
child Type
0 text node (or white space node)
1 element node <title>
2 text node
3 element node <author>
4 text node
5 element node <year>
6 text node
7 element node <price>
The code seeks only element nodes (nodeType =1) so processing proceeds only if (y.nodeType == 1);
Et voila, the output is:
1 title
3 author
5 year
7 price
[1]: https://oracle.com/technical-resources/articles/wang-whitespace.html
Upvotes: 0
Reputation: 2703
Your code evaluates only "element nodes" because of if (y.nodeType == 1)
.
Here is example with all nodes:
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="web">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
<book category="web" cover="paperback">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>`;
function getXmlFromText(xml) {
parser = new DOMParser();
return parser.parseFromString(xml, "text/xml");
}
function getNodeTypeStr(nodeType) {
if (nodeType == 1) return 'ELEMENT_NODE';
if (nodeType == 3) return 'TEXT_NODE';
return 'Read the DOCS: https://www.w3schools.com/xml/dom_nodetype.asp';
}
function myFunction(xmlDoc) {
var x, y, i, xlen, txt;
//xmlDoc = xml.responseXML;
x = xmlDoc.getElementsByTagName("book")[0];
xlen = x.childNodes.length;
y = x.firstChild;
txt = ""; var txt2 = '';
for (i = 0; i < xlen; i++) {
if (y.nodeType == 1) {
txt += i + " " + y.nodeName + "<br>";
}
txt2 += i + ' - ' + y.nodeName + ' - ' + getNodeTypeStr(y.nodeType) + ' - ' + y.nodeValue + '<br>';
y = y.nextSibling;
}
document.getElementById("demo").innerHTML = txt;
document.getElementById("allnodes").innerHTML = txt2;
}
myFunction(getXmlFromText(xml));
div {
padding: 2px;
border: 1px solid gray;
margin-bottom: 4px;
}
Only element nodes:
<div id="demo"></div>
All nodes:
<div id="allnodes"></div>
Packed XML example:
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="cooking">
<title lang="en">Everyday Italian</title><author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="children">
<title lang="en">Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
<book category="web">
<title lang="en">XQuery Kick Start</title>
<author>James McGovern</author>
<author>Per Bothner</author>
<author>Kurt Cagle</author>
<author>James Linn</author>
<author>Vaidyanathan Nagarajan</author>
<year>2003</year>
<price>49.99</price>
</book>
<book category="web" cover="paperback">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>`;
function getXmlFromText(xml) {
parser = new DOMParser();
return parser.parseFromString(xml, "text/xml");
}
function getNodeTypeStr(nodeType) {
if (nodeType == 1) return 'ELEMENT_NODE';
if (nodeType == 3) return 'TEXT_NODE';
return 'Read the DOCS: https://www.w3schools.com/xml/dom_nodetype.asp';
}
function myFunction(xmlDoc) {
var x, y, i, xlen, txt;
//xmlDoc = xml.responseXML;
x = xmlDoc.getElementsByTagName("book")[0];
xlen = x.childNodes.length;
y = x.firstChild;
txt = ""; var txt2 = '';
for (i = 0; i < xlen; i++) {
if (y.nodeType == 1) {
txt += i + " " + y.nodeName + "<br>";
}
txt2 += i + ' - ' + y.nodeName + ' - ' + getNodeTypeStr(y.nodeType) + ' - ' + y.nodeValue + '<br>';
y = y.nextSibling;
}
document.getElementById("demo").innerHTML = txt;
document.getElementById("allnodes").innerHTML = txt2;
}
myFunction(getXmlFromText(xml));
div {
padding: 2px;
border: 1px solid gray;
margin-bottom: 4px;
}
Only element nodes:
<div id="demo"></div>
All nodes:
<div id="allnodes"></div>
Upvotes: 1
Reputation: 815
It is because of the validation y.nodeType == 1
when that's true it storages in txt += i + " " + y.nodeName + "<br>";
; this means that when y.nodeType == 1
is true
i
is 1 in the next loop when i
is 2 y.nodeType == 1
is false, then on next loop when i
is 3 y.nodeType == 1
is true
and so.
Upvotes: 0