Here is a couple of classes to parse xml with GWT, the js code is taken
(with some modifications) from
ajaxslt(http://goog-ajaxslt.sourceforge.net/) . Here is how to use it:
String xml = "<element att=\"some attribute\">some text</element>";
Document doc = Document.xmlParse(xml);
Node node0 = (Node)doc.getChildren().get(0);
node0.getName(); // "element"
node0.getValue(); // null
node0.getAttribute("att"); // "some attribute"
node0.getType(); // DOM_ELEMENT_NODE
Node node1 = (Node)node.getChildNodes().get(0);
node1.getName(); // #text
node1.getValue(); // "some text"
node1.getType(); // DOM_TEXT_NODE
this GWT is a lot of fun :)
--------------------------------------------------------------------------- --------------
package com.test.client.xml;
import java.util.ArrayList;
import com.google.gwt.core.client.JavaScriptObject;
public class Document {
private ArrayList childNodes = new ArrayList();
public static final String DOM_ELEMENT_NODE = "DOM_ELEMENT_NODE";
public static final String DOM_TEXT_NODE = "DOM_TEXT_NODE";
Document() {
}
/...@com.test.client.xml.Document::newDocument()
public static Document newDocument() {
return new Document();
}
/...@com.test.client.xml.Document::createNode(Ljava/lang/String;)
public Node createNode(String name) {
return new Node(DOM_ELEMENT_NODE, name, null, this);
}
/...@com.test.client.xml.Document::createTextNode(Ljava/lang/String;)
public Node createTextNode(String value) {
return new Node(DOM_TEXT_NODE, "#text", value, this);
}
/...@com.test.client.xml.Document::appendChild(Lcom/test/client/xml/Node;)
public void appendChild(Node child) {
childNodes.add(child);
}
/...@com.test.client.xml.Document::xmlResolveEntities(Ljava/lang/String;)
public static native JavaScriptObject xmlResolveEntities(String s)
/*-{
var parts =
@com.test.client.xml.Document::stringSplit(Ljava/lang/String;Ljava/lang/Str ing;)(s,
'&');
var ret = parts[0];
for (var i = 1; i < parts.length; ++i) {
var rp =
@com.test.client.xml.Document::stringSplit(Ljava/lang/String;Ljava/lang/Str ing;)(parts[i],
';');
if (rp.length == 1) {
// no entity reference: just a & but no ;
ret += parts[i];
continue;
}
var ch;
switch (rp[0]) {
case 'lt':
ch = '<';
break;
case 'gt':
ch = '>';
break;
case 'amp':
ch = '&';
break;
case 'quot':
ch = '"';
break;
case 'apos':
ch = '\'';
break;
case 'nbsp':
ch = String.fromCharCode(160);
break;
default:
// Cool trick: let the DOM do the entity decoding. We assign
// the entity text through non-W3C DOM properties and read it
// through the W3C DOM. W3C DOM access is specified to
resolve
// entities.
var span = $wnd.document.createElement('span');
span.innerHTML = '&' + rp[0] + '; ';
ch = span.childNodes[0].nodeValue.charAt(0);
}
ret += ch + rp[1];
}
return ret;
}-*/
;
/...@com.test.client.xml.Document::stringSplit(Ljava/lang/String;Ljava/lang/Str ing;)
private static native JavaScriptObject stringSplit(String s, String c)
/*-{
var a = s.indexOf(c);
if (a == -1) {
return [ s ];
}
var parts = [];
parts.push(s.substr(0,a));
while (a != -1) {
var a1 = s.indexOf(c, a + 1);
if (a1 != -1) {
parts.push(s.substr(a + 1, a1 - a - 1));
} else {
parts.push(s.substr(a + 1));
}
a = a1;
}
return parts;
}-*/
;
public static native Document xmlParse(String xml) /*-{
var regex_empty = /\/$/;
// See also <http://www.w3.org/TR/REC-xml/#sec-common-syn> for
// allowed chars in a tag and attribute name. TODO(mesch): the
// following is still not completely correct.
var regex_tagname = /^([\w:-]*)/;
var regex_attribute = /([\w:-]+)\s?=\s?('([^\']*)'|"([^\"]*)")/g;
var xmldoc = @com.test.client.xml.Document::newDocument()();
var root = xmldoc;
// For the record: in Safari, we would create native DOM nodes, but
// in Opera that is not possible, because the DOM only allows HTML
// element nodes to be created, so we have to do our own DOM nodes.
// xmldoc = document.implementation.createDocument('','',null);
// root = xmldoc; // .createDocumentFragment();
// NOTE(mesch): using the DocumentFragment instead of the Document
// crashes my Safari 1.2.4 (v125.12).
var stack = [];
var parent = root;
stack.push(parent);
var x =
@com.test.client.xml.Document::stringSplit(Ljava/lang/String;Ljava/lang/Str ing;)(xml,
'<');
for (var i = 1; i < x.length; ++i) {
var xx =
@com.test.client.xml.Document::stringSplit(Ljava/lang/String;Ljava/lang/Str ing;)(x[i],
'>');
var tag = xx[0];
var text =
@com.test.client.xml.Document::xmlResolveEntities(Ljava/lang/String;)(xx[1]
|| '');
if (tag.charAt(0) == '/') {
stack.pop();
parent = stack[stack.length-1];
} else if (tag.charAt(0) == '?') {
// Ignore XML declaration and processing instructions
} else if (tag.charAt(0) == '!') {
// Ignore notation and comments
} else {
var empty = tag.match(regex_empty);
var tagname = regex_tagname.exec(tag)[1];
var node =
xmld...@com.test.client.xml.Document::createNode(Ljava/lang/String;)(tagname);
var att;
while (att = regex_attribute.exec(tag)) {
var val =
@com.test.client.xml.Document::xmlResolveEntities(Ljava/lang/String;)(att[3 ]
|| att[4] || '');
no...@com.test.client.xml.Node::setAttribute(Ljava/lang/String;Ljava/lang/String ;)(att[1],
val);
}
//TODO polymorphism here would be nice
if(parent == xmldoc) {
xmld...@com.test.client.xml.Document::appendChild(Lcom/test/client/xml/Node;)(node );
}
else {
pare...@com.test.client.xml.Node::appendChild(Lcom/test/client/xml/Node;)(node);
}
if (!empty) {
parent = node;
stack.push(node);
}
}
if (text && parent != root) {
if(parent == xmldoc) {
xmld...@com.test.client.xml.Document::appendChild(Lcom/test/client/xml/Node;)(xmld...@com.test.client.xml.Document::createTextNode(Ljava/lang/String;)(text));
}
else {
pare...@com.test.client.xml.Node::appendChild(Lcom/test/client/xml/Node;)(xmld...@com.test.client.xml.Document::createTextNode(Ljava/lang/String;)(text));
}
}
}
return xmldoc;
}-*/
;
/**
* @return Returns the childNodes.
*/
public ArrayList getChildren() {
return childNodes;
}
}
package com.test.client.xml;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class Node {
private Map attributes = new HashMap();
private ArrayList childNodes = new ArrayList();
private String type;
private String name;
private String value;
private Document document;
private Node parent;
Node(String nodeType, String nodeName, String nodeValue, Document
ownerDocument) {
this.type = nodeType;
this.name = nodeName;
this.value = nodeValue;
this.document = ownerDocument;
}
/...@com.test.client.xml.Node::appendChild(Lcom/test/client/xml/Node;)
public void appendChild(Node child) {
child.setParent(this);
childNodes.add(child);
}
public String getAttribute(String name) {
return (String)attributes.get(name);
}
/...@com.test.client.xml.Node::appendChild(Ljava/lang/String;Ljava/lang/String; Ljava/lang/String;)
public void setAttribute(String name, String value) {
attributes.put(name, value);
}
public Node getParent() {
return parent;
}
private void setParent(Node parent) {
this.parent = parent;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public ArrayList getChildNodes() {
return childNodes;
}
public Document getDocument() {
return document;
}
}