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.