Web Programming Step by Step, 2nd Edition

Lecture 19: XML

Reading: 12.3, 12.5

Except where otherwise noted, the contents of this document are Copyright 2012 Marty Stepp, Jessica Miller, and Victoria Kirst. All rights reserved. Any redistribution, reproduction, transmission, or storage of part or all of the contents in any form is prohibited without the author's expressed written permission.

Valid HTML5 Valid CSS

Storing structured data in arbitrary text formats (bad)

My note:
BEGIN
	FROM: Alice Smith (alice@example.com)
	TO: Robert Jones (roberto@example.com)
	SUBJECT: Tomorrow's "Birthday Bash" event!
	MESSAGE (english):
		Hey Bob,
		Don't forget to call me this weekend!
	PRIVATE: true
END

XML: A better way of storing data

<?xml version="1.0" encoding="UTF-8"?>
<note private="true">
	<from>Alice Smith (alice@example.com)</from>
	<to>Robert Jones (roberto@example.com)</to>
	<subject>Tomorrow's "Birthday Bash" event!</subject>
	<message language="english">
		Hey Bob, Don't forget to call me this weekend!
	</message>
</note>

What is XML?

Anatomy of an XML file

<?xml version="1.0" encoding="UTF-8"?>      <!-- XML prolog -->
<note private="true">                       <!-- root element -->
	<from>Alice Smith (alice@example.com)</from>
	<to>Robert Jones (roberto@example.com)</to>
	<subject>Tomorrow's "Birthday Bash" event!</subject>
	<message language="english">
		Hey Bob, Don't forget to call me this weekend!
	</message>
</note>

Uses of XML

What tags are legal in XML?

<measure number="1">
	<attributes>
		<divisions>1</divisions>
		<key><fifths>0</fifths></key>
		<time><beats>4</beats></time>
		<clef>
			<sign>G</sign><line>2</line>
		</clef>
	</attributes>
	<note>
		<pitch>
			<step>C</step>
			<octave>4</octave>
		</pitch>
		<duration>4</duration>
		<type>whole</type>
	</note>
</measure>

XML and Ajax

Ajax bleach

Fetching XML using Ajax (template)

node tree
var ajax = new XMLHttpRequest();
ajax.onload = functionName;
ajax.open("GET", url, true);
ajax.send();
...
function functionName() {
	do something with this.responseXML;
}

XML DOM tree structure

node tree
<?xml version="1.0" encoding="UTF-8"?>
<categories> 
  <category>children</category> 
  <category>computers</category> 
  ... 
</categories>

Interacting with XML DOM nodes

node tree

To get an array of nodes:

var elms = node.getElementsByTagName("tag");
var elms = node.querySelectorAll("selector");  // all elements
var elm  = node.querySelector("selector");     // first element

To get the text inside of a node:

var text = node.textContent;  // or,
var text = node.firstChild.nodeValue;

To get the value of a given attribute on a node:

var attrValue = node.getAttribute("name");

Differences from HTML DOM

Don't usually use getElementById because XML nodes don't have IDs or classes.

var div = document.getElementById("main");

Can't get/set the text inside of a node using innerHTML:

var text = div.innerHTML;

Can't get an attribute's value using .attributeName:

var imageUrl = document.getElementById("myimage").src;

Ajax XML DOM example

<?xml version="1.0" encoding="UTF-8"?>
<employees>
	<lawyer money="99999.00" />
	<janitor name="Ed"> <vacuum model="Hoover" /> </janitor>
	<janitor name="Bill">no vacuum, too poor</janitor>
</employees>
// how much money does the lawyer make?
var lawyer = this.responseXML.querySelector("lawyer");
var salary = parseFloat(lawyer.getAttribute("money"));      // 99999.0

var janitors = this.responseXML.querySelectorAll("janitor");   // array of 2 janitors
var vacModel = janitors[0].querySelector("vacuum").getAttribute("model");  // "Hoover"
var excuse = janitors[1].textContent;  // "no vacuum, too poor"

Larger XML file example

<?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="computers">
		<title lang="en">XQuery Kick Start</title>
		<author>James McGovern</author>
		<year>2003</year><price>49.99</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="computers">
		<title lang="en">Learning XML</title>
		<author>Erik T. Ray</author>
		<year>2003</year><price>39.95</price>
	</book>
	<!-- you can play with this XML in the console as 'this.responseXML2' -->
</bookstore>

Navigating node tree example

// make a paragraph for each book about computers
var books = this.responseXML.getElementsByTagName("book");
for (var i = 0; i < books.length; i++) {
	var category = books[i].getAttribute("category");
	if (category == "computers") {
		// extract data from XML
		var title = books[i].querySelector("title").textContent;
		var author = books[i].querySelector("author").textContent;
		
		// make an HTML <p> tag containing data from XML
		var p = document.createElement("p");
		p.innerHTML = title + ", by " + author;
		document.body.appendChild(p);
	}
}

Exercise: Late day distribution

Exercise: Animal game

The Animal Game

Practice problem: Animal game (cont'd)

Attacking the problem

Questions we should ask ourselves:

Debugging responseXML in Firebug

Firebug Debug Ajax

Full list of XML DOM properties

Schemas and Doctypes