document.implementation.createDocument() MSXML2.DOMDocument. /** * Create a new Document object. If no arguments are specified, * the document will be empty. If a root tag is specified, the document * will contain that single root tag. If the root tag has a namespace * prefix, the second argument must specify the URL that identifies the * namespace. */ XML.newDocument = function(rootTagName, namespaceURL) { if (!rootTagName) rootTagName = ""; if (!namespaceURL) namespaceURL = ""; if (document.implementation && document.implementation.createDocument) { // This is the W3C standard way to do it return document.implementation.createDocument(namespaceURL, rootTagName, null); } else { // This is the IE way to do it // Create an empty document as an ActiveX object // If there is no root element, this is all we have to do var doc = new ActiveXObject("MSXML2.DOMDocument"); // If there is a root tag, initialize the document if (rootTagName) { // Look for a namespace prefix var prefix = ""; var tagname = rootTagName; var p = rootTagName.indexOf(':'); if (p != -1) { prefix = rootTagName.substring(0, p); tagname = rootTagName.substring(p+1); } // If we have a namespace, we must have a namespace prefix // If we don't have a namespace, we discard any prefix if (namespaceURL) { if (!prefix) prefix = "a0"; // What Firefox uses } else prefix = ""; // Create the root element (with optional namespace) as a // string of text var text = "<" + (prefix?(prefix+":"):"") + tagname + (namespaceURL ?(" xmlns:" + prefix + '="' + namespaceURL +'"') :"") + "/>"; // And parse that text into the empty document doc.loadXML(text); } return doc; } };
load() method. /** * Synchronously load the XML document at the specified URL and * return it as a Document object */ XML.load = function(url) { // Create a new document the previously defined function var xmldoc = XML.newDocument(); xmldoc.async = false; // We want to load synchronously xmldoc.load(url); // Load and parse return xmldoc; // Return the document };
/** * Asynchronously load and parse an XML document from the specified URL. * When the document is ready, pass it to the specified callback function. * This function returns immediately with no return value. */ XML.loadAsync = function(url, callback) { var xmldoc = XML.newDocument(); // If we created the XML document using createDocument, use // onload to determine when it is loaded if (document.implementation && document.implementation.createDocument) { xmldoc.onload = function() { callback(xmldoc); }; } // Otherwise, use onreadystatechange as with XMLHttpRequest else { xmldoc.onreadystatechange = function() { if (xmldoc.readyState == 4) callback(xmldoc); }; } // Now go start the download and parsing xmldoc.load(url); };
/** * Parse the XML document contained in the string argument and return * a Document object that represents it. */ XML.parse = function(text) { if (typeof DOMParser != "ftp://ftp.") { // Mozilla, Firefox, and related browsers return (new DOMParser()).parseFromString(text, "application/xml"); } else if (typeof ActiveXObject != "undefined") { // Internet Explorer. var doc = XML.newDocument(); // Create an empty document doc.loadXML(text); // Parse text into it return doc; // Return it } else { // As a last resort, try loading the document from a data: URL // This is supposed to work in Safari. Thanks to Manos Batsis and // his Sarissa library (sarissa.sourceforge.net) for this technique. var url = "data:text/xml;charset=utf-8," + encodeURIComponent(text); var request = new XMLHttpRequest(); request.open("GET", url, false); request.send(null); return request.responseXML; } };
getElementById only works if the attribute is
of type “id” as specified in the xsd (XML
Schema Definition) or DTD (works for me in Firefox with XHTML).getAttribute() and
setAttribute(). You cannot use properties to
access attributes./** * Extract data from the specified XML document and format it as an HTML table. * Append the table to the specified HTML element. (If element is a string, * it is taken as an element ID, and the named element is looked up.) * * The schema argument is a JavaScript object that specifies what data is to * be extracted and how it is to be displayed. The schema object must have a * property named "rowtag" that specifies the tag name of the XML elements that * contain the data for one row of the table. The schema object must also have * a property named "columns" that refers to an array. The elements of this * array specify the order and content of the columns of the table. Each * array element may be a string or a JavaScript object. If an element is a * string, that string is used as the tag name of the XML element that contains * table data for the column, and also as the column header for the column. * If an element of the columns[] array is an object, it must have one property * named "tagname" and one named "label". The tagname property is used to * extract data from the XML document and the label property is used as the * column header text. If the tagname begins with an @ character, it is * an attribute of the row element rather than a child of the row. */ function makeTable(xmldoc, schema, element) { // Create the <table> element var table = document.createElement("table"); // Create the header row of <th> elements in a <tr> in a <thead> var thead = document.createElement("thead"); var header = document.createElement("tr"); for(var i = 0; i < schema.columns.length; i++) { var c = schema.columns[i]; var label = (typeof c == "string")?c:c.label; var cell = document.createElement("th"); cell.appendChild(document.createTextNode(label)); header.appendChild(cell); } // Put the header into the table thead.appendChild(header); table.appendChild(thead); // The remaining rows of the table go in a <tbody> var tbody = document.createElement("tbody"); table.appendChild(tbody); // Now get the elements that contain our data from the xml document var xmlrows = xmldoc.getElementsByTagName(schema.rowtag); // Loop through these elements. Each one contains a row of the table for(var r=0; r < xmlrows.length; r++) { // This is the XML element that holds the data for the row var xmlrow = xmlrows[r]; // Create an HTML element to display the data in the row var row = document.createElement("tr"); // Loop through the columns specified by the schema object for(var c = 0; c < schema.columns.length; c++) { var sc = schema.columns[c]; var tagname = (typeof sc == "string")?sc:sc.tagname; var celltext; if (tagname.charAt(0) == '@') { // If the tagname begins with '@', it is an attribute name celltext = xmlrow.getAttribute(tagname.substring(1)); } else { // Find the XML element that holds the data for this column var xmlcell = xmlrow.getElementsByTagName(tagname)[0]; // Assume that element has a text node as its first child var celltext = xmlcell.firstChild.data; } // Create the HTML element for this cell var cell = document.createElement("td"); // Put the text data into the HTML cell cell.appendChild(document.createTextNode(celltext)); // Add the cell to the row row.appendChild(cell); } // And add the row to the tbody of the table tbody.appendChild(row); } // Set an HTML attribute on the table element by setting a property. // Note that in XML we must use setAttribute() instead. table.frame = "border"; // Now that we've created the HTML table, add it to the specified element. // If that element is a string, assume it is an element ID. if (typeof element == "string") element = document.getElementById(element); element.appendChild(table); }
function displayAddressBook(){ var schema = { rowtag: "contact", columns: [ {tagname: "@name", label: "Name"}, {tagname: "email", label: "Address"} ] }; var xmldoc = XML.load("addresses.xml"); makeTable(xmldoc, schema, "addresses"); }addresses.xml:
<?xml version="1.0" encoding="ISO-8859-1"?> <contacts> <contact name="Able Baker"><email>able@example.com</email></contact> <contact name="Careful Dodger"><email>dodger@example.com</email></contact> <contact name="Eager Framer" personal="true"><email>framer@example.com</email></contact> </contacts><div id="addresses"><!--table here--> </div>
XSLTProcessor object while IE has
document.transformNode() method. <?xml version="1.0"?><!-- this is an xml document --> <!-- declare the xsl namespace to distinguish xsl tags from html tags --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html"/> <!-- When we see the root element, output the HTML framework of a table --> <xsl:template match="/"> <table> <tr><th>Name</th><th>E-mail Address</th></tr> <xsl:apply-templates/> <!-- and recurse for other templates --> </table> </xsl:template> <!-- When we see a <contact> element... --> <xsl:template match="contact"> <tr> <!-- Begin a new row of the table --> <!-- Use the name attribute of the contact as the first column --> <td><xsl:value-of select="@name"/></td> <xsl:apply-templates/> <!-- and recurse for other templates --> </tr> </xsl:template> <!-- When we see an <email> element, output its content in another cell --> <xsl:template match="email"> <td><xsl:value-of select="."/></td> </xsl:template> </xsl:stylesheet>
<?xml version="1.0" encoding="ISO-8859-1" ?> <?xml-stylesheet type="text/xsl" href="./feedtohtml.xsl" ?> <myrss> <!--changed from rss because firefox is too smart and asks me if I want to subscribe. --> <channel xmlns:html="http://www.w3.org/1999/xhtml"> <title>CSCE 782: Fall 2006</title> <link>http://jmvidal.cse.sc.edu/csce782/</link> <description>Announcements.</description> <language>en-us</language> <copyright>Copyright 2006 jmvidal</copyright> <docs>http://blogs.law.harvard.edu/tech/rss/</docs> <lastBuildDate>Mon, 04 Dec 2006 15:16:10 EST</lastBuildDate> <item> <title>Final Project Handout</title> <pubDate>Mon, 04 Dec 2006 15:14:42 EST</pubDate> <guid>http://jmvidal.cse.sc.edu/csce782/news.rss#1165263282</guid> <description> OK, I have posted the final project handout. Let me know if you have questions. </description> <link>http://jmvidal.cse.sc.edu/csce782/news.rss</link> </item> <item> <title>Last Week: No Classes</title> <pubDate>Thu, 30 Nov 2006 09:06:43 EST</pubDate> <guid>http://jmvidal.cse.sc.edu/csce782/news.rss#1164895603</guid> <description> We will not be meeting during the last week. But, I will be in my office during class time in case you want to talk about your final project. </description> <link>http://jmvidal.cse.sc.edu/csce782/news.rss</link> </item> <item> <title>Test 2</title> <pubDate>Tue, 28 Nov 2006 06:40:37 EST</pubDate> <guid>http://jmvidal.cse.sc.edu/csce782/news.rss#1164714037</guid> <description> In case I did not mention it in class, Test 2 will be based solely on the rest of the book chapters. That is, it does not cover the papers I presented in class. </description> <link>http://jmvidal.cse.sc.edu/csce782/news.rss</link> </item> </channel> </myrss>feedtohtml.xsl:
<?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/myrss"> <html> <head> <link href="xsl.css" rel="stylesheet" type="text/css" /> <style type="text/css"> body { font-size:0.83em; } </style> </head> <body> <div id="logo"> <xsl:element name="a"> <xsl:attribute name="href"> <xsl:value-of select="channel/link" /> </xsl:attribute> <xsl:value-of select="channel/title" /> </xsl:element> </div> <div class="Snippet" style="border-width:0; background-color:#FFF; margin:1em"> <div class="titleWithLine"> <xsl:value-of select="channel/description" /> </div> <dl style="padding-right:1em"> <xsl:for-each select="channel/item"> <dd> <xsl:value-of select="title"/> </dd> <dt> <xsl:value-of select="description" disable-output-escaping="yes"/><br /> <span class="comments"><xsl:value-of select="pubDate" /></span> </dt> </xsl:for-each> </dl> </div> <div id="footer"> <xsl:value-of select="channel/copyright" /> </div> </body> </html> </xsl:template> </xsl:stylesheet>
<?xml version="1.0" encoding="ISO-8859-1"?> <contacts> <contact name="Able Baker"><email>able@example.com</email></contact> <contact name="Careful Dodger"><email>dodger@example.com</email></contact> <contact name="Eager Framer" personal="true"><email>framer@example.com</email></contact> </contacts>Let context = contacts:
contact set of all <contact> tags.contact[1] first <contact> tag.contact[last()] last <contact> tag.contact/email all <email> children of <contact>contact/@name value of name attribute of contact childrencontact[@personal="true"] all <contact> tags with attribute personal = "true"/** * XML.XPathExpression is a class that encapsulates an XPath query and its * associated namespace prefix-to-URL mapping. Once an XML.XPathExpression * object has been created, it can be evaluated one or more times (in one * or more contexts) using the getNode() or getNodes() methods. * * The first argument to this constructor is the text of the XPath expression. * * If the expression includes any XML namespaces, the second argument must * be a JavaScript object that maps namespace prefixes to the URLs that define * those namespaces. The properties of this object are the prefixes, and * the values of those properties are the URLs. */ XML.XPathExpression = function(xpathText, namespaces) { this.xpathText = xpathText; // Save the text of the expression this.namespaces = namespaces; // And the namespace mapping if (document.createExpression) { // If we're in a W3C-compliant browser, use the W3C API // to compile the text of the XPath query this.xpathExpr = document.createExpression(xpathText, // This function is passed a // namespace prefix and returns the URL. function(prefix) { return namespaces[prefix]; }); } else { // Otherwise, we assume for now that we're in IE and convert the // namespaces object into the textual form that IE requires. this.namespaceString = ""; if (namespaces != null) { for(var prefix in namespaces) { // Add a space if there is already something there if (this.namespaceString) this.namespaceString += ' '; // And add the namespace this.namespaceString += 'xmlns:' + prefix + '="' + namespaces[prefix] + '"'; } } } }; /** * This is the getNodes() method of XML.XPathExpression. It evaluates the * XPath expression in the specified context. The context argument should * be a Document or Element object. The return value is an array * or array-like object containing the nodes that match the expression. */ XML.XPathExpression.prototype.getNodes = function(context) { if (this.xpathExpr) { // If we are in a W3C-compliant browser, we compiled the // expression in the constructor. We now evaluate that compiled // expression in the specified context var result = this.xpathExpr.evaluate(context, // This is the result type we want XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); // Copy the results we get into an array. var a = new Array(result.snapshotLength); for(var i = 0; i < result.snapshotLength; i++) { a[i] = result.snapshotItem(i); } return a; } else { // If we are not in a W3C-compliant browser, attempt to evaluate // the expression using the IE API. try { // We need the Document object to specify namespaces var doc = context.ownerDocument; // If the context doesn't have ownerDocument, it is the Document if (doc == null) doc = context; // This is IE-specific magic to specify prefix-to-URL mapping doc.setProperty("SelectionLanguage", "XPath"); doc.setProperty("SelectionNamespaces", this.namespaceString); // In IE, the context must be an Element not a Document, // so if context is a document, use documentElement instead if (context == doc) context = doc.documentElement; // Now use the IE method selectNodes() to evaluate the expression return context.selectNodes(this.xpathText); } catch(e) { // If the IE API doesn't work, we just give up throw "XPath not supported by this browser."; } } } /** * This is the getNode() method of XML.XPathExpression. It evaluates the * XPath expression in the specified context and returns a single matching * node (or null if no node matches). If more than one node matches, * this method returns the first one in the document. * The implementation differs from getNodes() only in the return type. */ XML.XPathExpression.prototype.getNode = function(context) { if (this.xpathExpr) { var result = this.xpathExpr.evaluate(context, // We just want the first match XPathResult.FIRST_ORDERED_NODE_TYPE, null); return result.singleNodeValue; } else { try { var doc = context.ownerDocument; if (doc == null) doc = context; doc.setProperty("SelectionLanguage", "XPath"); doc.setProperty("SelectionNamespaces", this.namespaceString); if (context == doc) context = doc.documentElement; // In IE call selectSingleNode instead of selectNodes return context.selectSingleNode(this.xpathText); } catch(e) { throw "XPath not supported by this browser."; } } }; // A utility to create an XML.XPathExpression and call getNodes() on it XML.getNodes = function(context, xpathExpr, namespaces) { return (new XML.XPathExpression(xpathExpr, namespaces)).getNodes(context); }; // A utility to create an XML.XPathExpression and call getNode() on it XML.getNode = function(context, xpathExpr, namespaces) { return (new XML.XPathExpression(xpathExpr, namespaces)).getNode(context); };
<?xml version="1.0" encoding="ISO-8859-1"?> <contacts> <contact name="Able Baker"><email>able@example.com</email></contact> <contact name="Careful Dodger"><email>dodger@example.com</email></contact> <contact name="Eager Framer" personal="true"><email>framer@example.com</email></contact> </contacts>
var xmldoc = XML.load('addresses.xml'); var query = 'contacts/contact[@personal="true"]'; var serializer = new XMLSerializer();serializer.serializeToString(XML.getNode(xmldoc,query)) [6]
This talk available at http://jmvidal.cse.sc.edu/talks/javascriptxml/
Copyright © 2009 José M. Vidal
.
All rights reserved.
28 February 2007, 02:14PM