complete E4X (ECMA 357) parser
// 10.1.1
var order = <order>
<customer>
<firstname>John</firstname>
<lastname>Doe</lastname>
</customer>
<item>
<description>Big Screen Television</description>
<price>1299.99</price>
<quantity>1</quantity>
</item>
</order>
// Construct the full customer name
var name = order.customer.firstname + " " + order.customer.lastname;
// Calculate the total price
var total = order.item.price * order.item.quantity;
// 10.3.1
var John = "<employee><name>John</name><age>25</age></employee>";
var Sue = "<employee><name>Sue</name><age>32</age></employee>";
var tagName = "employees";
var employees = new XML("<" + tagName +">" + John + Sue + "</" + tagName +">");
// 10.3.2
function createTable() {
var doc = XML(document); // create an E4X wrapper for the document var mytablebody = doc..body.TABLE.TBODY;
for (var j=0;j<2;j++) {
mytablebody.TR[j] = ""; // append an empty table row
for (var i=0;i<2;i++) // append a cell with some content
mytablebody.TR[j].TD[i] = "cell is row " + j + ", column " + i;
}
doc..body.TABLE.@border = 2; // set the border attribute of the table
}
// 10.4.1
var John = "<employee><name>John</name><age>25</age></employee>";
var Sue = "<employee><name>Sue</name><age>32</age></employee>";
var list = new XMLList(John + Sue);
// 11.1.2
// Create a SOAP message
var message = <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<soap:Body>
<m:GetLastTradePrice xmlns:m="http://mycompany.com/stocks">
<symbol>DIS</symbol>
</m:GetLastTradePrice>
</soap:Body>
</soap:Envelope>
// declare the SOAP and stocks namespaces
var soap = new Namespace("http://schemas.xmlsoap.org/soap/envelope/");
var stock = new Namespace ("http://mycompany.com/stocks");
// extract the soap encoding style and body from the soap message
var encodingStyle = message.@soap::encodingStyle;
var body = message.soap::Body;
// change the stock symbol
message.soap::Body.stock::GetLastTradePrice.symbol = "MYCO";
// 11.1.4
// an XML object representing a person with a name and age
var person = <person><name>John</name><age>25</age></person>;
// a variable containing an XML object representing two employees
var e = <employees>
<employee id="1"><name>Joe</name><age>20</age></employee>
<employee id="2"><name>Sue</name><age>30</age></employee>
</employees>;
for (var i = 0; i < 10; i++)
e[i] = <employee id={i}> // compute id value
<name>{names[i].toUpperCase()}</name> // compute name value
<age>{ages[i]}</age> // compute age value
</employee>;
var tagname = "name";
var attributename = "id";
var attributevalue = 5;
var content = "Fred";
var x = <{tagname} {attributename}={attributevalue}>{content}</{tagname}>;
<name id="5">Fred</name>
// 11.1.5
var docfrag = <><name>Phil</name><age>35</age><hobby>skiing</hobby></>;
var emplist = <>
<employee id="0" ><name>Jim</name><age>25</age></employee>
<employee id="1" ><name>Joe</name><age>20</age></employee>
<employee id="2" ><name>Sue</name><age>30</age></employee>
</>;
// 11.2.1
var order = <order id = "123456" timestamp="Mon Mar 10 2003 16:03:25 GMT-0800 (PST)">
<customer>
<firstname>John</firstname>
<lastname>Doe</lastname>
</customer>
<item>
<description>Big Screen Television</description>
<price>1299.99</price>
<quantity>1</quantity>
</item>
</order>;
var customer = order.customer; // get the customer element from the order
var id = order.@id; // get the id attribute from the order
var orderChildren = order.*; // get all the child elements from the order element
varorderAttributes=order.@*; //getalltheattributesfromtheorderelement
// get the first (and only) order [treating single element as a list]
var firstOrder = order[0];
var order = <order>
<customer>
<firstname>John</firstname>
<lastname>Doe</lastname>
</customer>
<item id = "3456">
<description>Big Screen Television</description>
<price>1299.99</price>
<quantity>1</quantity>
</item>
<item id = "56789">
<description>DVD Player</description>
<price>399.99</price>
<quantity>1</quantity>
</item>
</order>;
var descriptions = order.item.description; // get the list of all item descriptions
var itemIds = order.item.@id; // get the list of all item id attributes
var secondItem = order.item[1]; // get second item by numeric index
var itemChildren = order.item.*; // get the list of all child elements in all items
var secondItemChild = order.item.*[1]; // get the second child from the list of all items
// 11.2.2
var rectangle = <rectangle>
<x>50</x>
<y>75</y>
<length>20</length>
<width>30</width>
</rectangle>;
var numRectangles = rectangle.length(); // returns 1 � number of <rectangle> elements
var rectangleLength = rectangle.length; // returns 20 � content of <length> element
rectangle.length = 50; // change the length element of the rectangle
// 11.2.2.1
var shipto= <shipto>
<name>Fred Jones</name>
<street>123 Foobar Ave.</street>
<citystatezip>Redmond, WA, 98008</citystatezip>
</shipto>
// calls String.toUpperCase on value of text node
var upperName = shipto.name.toUpperCase();
// calls String.split() on text node to parse address
var citystatezip = shipto.citystatezip.split(", ");
var state = citystatezip[1]; // line into individual city, state and zip values
var zip = citystatezip[2];
// 11.2.3
var e = <employees>
<employee id="1"><name>Joe</name><age>20</age></employee>
<employee id="2"><name>Sue</name><age>30</age></employee>
</employees>;
var names = e..name; // get all the names in e
// 11.2.4
var john = e.employee.(name == "John"); // employees with name John
var twoemployees = e.employee.(@id == 0 || @id == 1); // employees with id's 0 & 1
var emp = e.employee.(@id == 1).name; // name of employee with id 1
// get the two employees with ids 0 and 1 using a predicate
var twoEmployees = e..employee.(@id == 0 || @id == 1);
// get the two employees with the ids 0 and 1 using a for loop
var i = 0;
var twoEmployees = new XMLList();
for each (var p in e..employee) {
with (p) {
if (@id == 0 || @id == 1) {
twoEmployees[i++] = p;
}
}
}
// 11.3
delete order.customer.address; // delete the customer address
delete order.customer.@id; // delete the customer ID
delete order.item.price[0]; // delete the first item price
delete order.item; // delete all the items
// 11.4.1
// create an XMLList containing the elements <name>, <age> and <hobby>
var employeedata = <name>Fred</name> + <age>28</age> + <hobby>skiing</hobby>;
// create an XMLList containing three item elements extracted from the order element
var myitems = order.item[0] + order.item[2] + order.item[3];
// create a new XMLList containing all the items in the order plus one new one
var newitems = order.item + <item><description>new item</description></item>;
// add the prices of the first and third items in the order (coersion with unary +)
var totalPrice = +order.item[0].price + +order.item[2].price
// add the prices of the second and fourth items in the order (coersion using Number
// conversion function)
var totalPrice = Number(order.item[1].price) + Number(order.item[3].price)
// concatenate the street and the city of the customer's address (coersion with the empty
// string)
var streetcity = "" + order.customer.address.street + order.customer.address.city;
// concatenate the state and the zip of the customer's address (coersion using String
// conversion function)
var statezip = String(order.customer.address.state) + order.customer.address.zip;
// 11.6.1
// change the value of the id attribute on the second item
order.item[1].@id = 123;
// add a new attribute to the second item
order.item[1].@newattr = "new value";
// construct an attribute list containing all the ids in this order
order.@allids = order.item.@id;
item.price = 99.95; // change the price of the item
item.description = "Mobile Phone"; // change the description of the item
// 11.6.2
// set the name of the only customer in the order to Fred Jones
order.customer.name = "Fred Jones";
// replace all the hobbies for the only customer in the order
order.customer.hobby = "shopping";
// attempt to set the sale date of a single item.
order.item.saledate = "05-07-2002";
// replace all the employee's hobbies with their new favorite pastime
emps.employee.(@id == 3).hobby = "working";
// replace the first employee with George
e.employee[0] = <employee><name>George</name><age>27</age></employee>;
// add a new employee to the end of the employee list
e.employee[e.employee.length()] = <employee><name>Frank</name></employee>;
// 11.6.3
var e = <employees>
<employee id="1"><name>Joe</name><age>20</age></employee>
<employee id="2"><name>Sue</name><age>30</age></employee>
</employees>;
// insert employee 3 and 4 after the first employee
e.employee[0] += <employee id="3"><name>Fred</name></employee> +
<employee id="4"><name>Carol</name></employee>;
<employees>
<employee id="1"><name>Joe</name><age>20</age></employee>
<employee id="3"><name>Fred</name></employee>
<employee id="4"><name>Carol</name></employee>
<employee id="2"><name>Sue</name><age>30</age></employee>
</employees>;
var e = <employees>
<employee id="1"><name>Joe</name><age>20</age></employee>
<employee id="2"><name>Sue</name><age>30</age></employee>
</employees>;
// append employees 3 and 4 to the end of the employee list
e.employee += <employee id="3"><name>Fred</name></employee> +
<employee id="4"><name>Carol</name></employee>;
<employees>
<employee id="1"><name>Joe</name><age>20</age></employee>
<employee id="2"><name>Sue</name><age>30</age></employee>
<employee id="3"><name>Fred</name></employee>
<employee id="4"><name>Carol</name></employee>
</employees>;
// 12.1
// declare some namespaces and a default namespace for the current scope
var soap = new Namespace("http://schemas.xmlsoap.org/soap/envelope/");
var stock = new Namespace("http://mycompany.com/stocks");
default xml namespace = soap; // alternately, may specify full URI
// Create an XML initializer in the default (i.e., soap) namespace
var message = <Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
soap:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<Body>
<m:GetLastTradePrice xmlns:m="http://mycompany.com/stocks">
<symbol>DIS</symbol>
</m:GetLastTradePrice>
</Body>
</Envelope>
// extract the soap encoding style using a QualifiedIdentifier (unqualified attributes are in // no namespace)
var encodingStyle = message.@soap::encodingStyle;
//extract the body from the soap message using the default namespace
var body = message.Body;
// change the stock symbol using the default namespace and qualified names
message.Body.stock::GetLastTradePrice.stock::symbol = "MYCO";
// 12.2
// print all the employee names
for (var n in e..name) {
print ("Employee name: " + e..name[n]);
}
// print each child of the first item
for (var child in order.item[0].*) {
print("item child: " + order.item[0].*[child]);
}
// 12.3
// print all the employee names
for each (var n in e..name) {
print ("Employee name: " + n);
}
// print each child of the first item
for each (var child in order.item[0].*) {
print("item child: " + child);
}
// 13.4.3
var e = <employees>
<employee id="0" ><name>Jim</name><age>25</age></employee>
<employee id="1" ><name>Joe</name><age>20</age></employee>
</employees>;
// Add a new child element to the end of Jim's employee element
e.employee.(name == "Jim").appendChild(<hobby>snorkeling</hobby>);
// 13.4.4.4
// get the id of the employee named Jim
e.employee.(name == "Jim").attribute("id");
// 13.4.4.5
// print the attributes of an XML object
function printAttributes(x) {
for each (var a in x.attributes()) {
print("The attribute named " + a.name() + " has the value " + a);
}
}
// 13.4.4.6
var name = customer.child("name"); // equivalent to: var name = customer.name;
var secondChild = customer.child(1); // equivalent to: var secondChild = customer.*[1]
// 13.4.4.7
// Get the ordinal index of the employee named Joe.
var joeindex = e.employee.(name == "Joe").childIndex();
// 13.4.4.8
// Get child elements of first employee: returns an XMLList containing:
// <name>Jim</name>, <age>25</age> and <hobby>Snorkeling</hobby>
var emps = e.employee[0].children();
// 13.4.4.27
// Get the parent element of the second name in "e". Returns <employee id="1" ...
var firstNameParent = e..name[1].parent()
// 13.4.4.29
// Add a new child element to the front of John's employee element
e.employee.(name == "John").prependChild(<prefix>Mr.</prefix>);
// 13.4.4.32
// Replace the first employee record with an open staff requisition
employees.replace(0, <requisition status="open"/>);
// Replace all item elements in the order with a single empty item
order.replace("item", <item/>);
// 13.4.4.33
// Replace the entire contents of Jim's employee element
e.employee.(name == "Jim").setChildren(<name>John</name> + <age>35</age>);
// 13.4.4.39
var item = <item>
<description>Laptop Computer</description>
<price>2799.95</price>
<quantity>1</quantity>
</item>;
// returns "Description stored as <description>Laptop Computer</description>"
var logmsg = "Description stored as " + item.description.toXMLString();
// returns "Thank you for purchasing a Laptop Computer!" (with tags removed)
var message = "Thank you for purchasing a " + item.description + "!";
Syntax node location info (start, end):
Esprima with E4X is created and mantained by Yusuke Suzuki.