aoqi@0: #// Usage: jjs -scripting jsadapter_dom.js aoqi@0: aoqi@0: /* aoqi@0: * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. aoqi@0: * aoqi@0: * Redistribution and use in source and binary forms, with or without aoqi@0: * modification, are permitted provided that the following conditions aoqi@0: * are met: aoqi@0: * aoqi@0: * - Redistributions of source code must retain the above copyright aoqi@0: * notice, this list of conditions and the following disclaimer. aoqi@0: * aoqi@0: * - Redistributions in binary form must reproduce the above copyright aoqi@0: * notice, this list of conditions and the following disclaimer in the aoqi@0: * documentation and/or other materials provided with the distribution. aoqi@0: * aoqi@0: * - Neither the name of Oracle nor the names of its aoqi@0: * contributors may be used to endorse or promote products derived aoqi@0: * from this software without specific prior written permission. aoqi@0: * aoqi@0: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS aoqi@0: * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, aoqi@0: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR aoqi@0: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR aoqi@0: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, aoqi@0: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, aoqi@0: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR aoqi@0: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF aoqi@0: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING aoqi@0: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS aoqi@0: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. aoqi@0: */ aoqi@0: aoqi@0: // Simple example that demonstrates reading XML Rss feed aoqi@0: // to generate a HTML file from script and show it by browser aoqi@0: // Uses XML DOM parser and DOM element wrapped by script aoqi@0: // "proxy" (JSAdapter constructor) aoqi@0: aoqi@0: // Java classes used aoqi@0: var DocBuilderFac = Java.type("javax.xml.parsers.DocumentBuilderFactory"); aoqi@0: var Node = Java.type("org.w3c.dom.Node"); aoqi@0: var File = Java.type("java.io.File"); aoqi@0: var FileWriter = Java.type("java.io.FileWriter"); aoqi@0: var PrintWriter = Java.type("java.io.PrintWriter"); aoqi@0: aoqi@0: // constants from Node class aoqi@0: var ELEMENT_NODE = Node.ELEMENT_NODE; aoqi@0: var TEXT_NODE = Node.TEXT_NODE; aoqi@0: aoqi@0: // parse XML from uri and return Document aoqi@0: function parseXML(uri) { aoqi@0: var docBuilder = DocBuilderFac.newInstance().newDocumentBuilder(); aoqi@0: return docBuilder["parse(java.lang.String)"](uri); aoqi@0: } aoqi@0: aoqi@0: // get child Elements of given name of the parent element given aoqi@0: function getChildElements(elem, name) { aoqi@0: var nodeList = elem.childNodes; aoqi@0: var childElems = []; aoqi@0: var len = nodeList.length; aoqi@0: for (var i = 0; i < len; i++) { aoqi@0: var node = nodeList.item(i); aoqi@0: if (node.nodeType == ELEMENT_NODE && aoqi@0: node.tagName == name) { aoqi@0: childElems.push(wrapElement(node)); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return childElems; aoqi@0: } aoqi@0: aoqi@0: // get concatenated child text content of an Element aoqi@0: function getElemText(elem) { aoqi@0: var nodeList = elem.childNodes; aoqi@0: var len = nodeList.length; aoqi@0: var text = ''; aoqi@0: for (var i = 0; i < len; i++) { aoqi@0: var node = nodeList.item(i); aoqi@0: if (node.nodeType == TEXT_NODE) { aoqi@0: text += node.nodeValue; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: return text; aoqi@0: } aoqi@0: aoqi@0: // Wrap DOM Element object as a convenient script object aoqi@0: // using JSAdapter. JSAdapter is like java.lang.reflect.Proxy aoqi@0: // in that it allows property access, method calls be trapped aoqi@0: // by 'magic' methods like __get__, __call__. aoqi@0: function wrapElement(elem) { aoqi@0: if (! elem) { aoqi@0: return elem; aoqi@0: } aoqi@0: return new JSAdapter() { aoqi@0: // getter to expose child elements and attributes by name aoqi@0: __get__: function(name) { aoqi@0: if (typeof name == 'string') { aoqi@0: if (name.startsWith('@')) { aoqi@0: var attr = elem.getAttributeNode(name.substring(1)); aoqi@0: return !attr? undefined : attr.value; aoqi@0: } aoqi@0: aoqi@0: var arr = getChildElements(elem, name); aoqi@0: if (arr.length == 1) { aoqi@0: // single child element, expose as single element aoqi@0: return arr[0]; aoqi@0: } else { aoqi@0: // multiple children of given name, expose as array aoqi@0: return arr; aoqi@0: } aoqi@0: } aoqi@0: return undefined; aoqi@0: }, aoqi@0: aoqi@0: __call__: function(name) { aoqi@0: // toString override to get text content of this Element aoqi@0: if (name == 'toString' || name == 'valueOf') { aoqi@0: return getElemText(elem); aoqi@0: } aoqi@0: return undefined; aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // generate HTML using here-doc and string interpolation aoqi@0: function getBooksHtml() { aoqi@0: var doc = parseXML("http://www.gutenberg.org/cache/epub/feeds/today.rss"); aoqi@0: // wrap document root Element as script convenient object aoqi@0: var rss = wrapElement(doc.documentElement); aoqi@0: print("rss file version " + rss['@version']); aoqi@0: aoqi@0: var str = < aoqi@0: ${rss.channel.title} aoqi@0: aoqi@0:

${rss.channel.description}

aoqi@0:

aoqi@0: Published on ${rss.channel.pubDate} aoqi@0:

aoqi@0: aoqi@0: HEAD aoqi@0: aoqi@0: var items = rss.channel.item; aoqi@0: for each (var i in items) { aoqi@0: str += < aoqi@0:
${i.title}
aoqi@0:
${i.description}
aoqi@0: aoqi@0: aoqi@0: LIST aoqi@0: } aoqi@0: str += < aoqi@0: aoqi@0: aoqi@0: END aoqi@0: return str; aoqi@0: } aoqi@0: aoqi@0: // write the string to the given file aoqi@0: function writeTo(file, str) { aoqi@0: var w = new PrintWriter(new FileWriter(file)); aoqi@0: try { aoqi@0: w.print(str); aoqi@0: } finally { aoqi@0: w.close(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: // generate books HTML aoqi@0: var str = getBooksHtml(); aoqi@0: aoqi@0: // write to file. __DIR__ is directory where aoqi@0: // this script is stored. aoqi@0: var file = new File(__DIR__ + "books.html"); aoqi@0: writeTo(file, str); aoqi@0: aoqi@0: // show it by desktop browser aoqi@0: try { aoqi@0: var Desktop = Java.type("java.awt.Desktop"); aoqi@0: Desktop.desktop.browse(file.toURI()); aoqi@0: } catch (e) { aoqi@0: print(e); aoqi@0: }