I have an XML response that I'd like to bind and display to a GXT grid.
The basic example I've found online says to do the following:
// defines the xml structure
ModelType type = new ModelType();
type.setRoot("records");
type.setRecordName("record");
type.addField("Sender", "Name");
type.addField("Email");
type.addField("Phone");
type.addField("State");
type.addField("Zip");
// use a http proxy to get the data
RequestBuilder builder = new RequestBuilder(RequestBuilder.GET,
GWT.getHostPageBaseURL() + "data/data.xml");
HttpProxy<String> proxy = new HttpProxy<String>(builder);
// need a loader, proxy, and reader
XmlLoadResultReader<ListLoadResult<ModelData>> reader = new XmlLoadResultReader<ListLoadResult<ModelData>>(
type);
final BaseListLoader<ListLoadResult<ModelData>> loader = new BaseListLoader<ListLoadResult<ModelData>>(
proxy, reader);
ListStore<ModelData> store = new ListStore<ModelData>(loader);
This works just fine if your XML is in a simple structure (ie no nested elements).
However, my XML is more like this:
<myRoot>
<myElement>
<first>
<time></time>
<place></place>
</first>
<second>
<time></time>
<place></place>
</second>
<third>
<time></time>
<place></place>
</third>
</myElement>
...
</myRoot>
How can I represent this using ModelType in order for the Grid to properly display the results?
The key is how you parse the XML document to build the ModelData
(extended here as ModelType
).
GXT showcase shows how to parse their example XML into beans, and you can use your favored XML parser to do the same.
here is a snippet from their repositories, edited based on your XML data to demonstrate how it's done:
public void parseXmlData() {
try {
// init parser / builder
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(getClass().getResourceAsStream("data.xml"));
doc.getDocumentElement().normalize();
// get first level
NodeList myElementNodeList = doc.getElementsByTagName("myElement");
// traverse first level
for (int s = 0; s < myElementNodeList.getLength(); s++) {
Node fstNode = myElementNodeList.item(s);
if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
Element fstElmnt = (Element) fstNode;
NodeList myElementChildren = fstElmnt.getChildNodes();
// traverse second level
for (int c = 0; c < myElementChildren.getLength(); c++) {
Node cNode = myElementChildren.item(s);
if (cNode.getNodeType() == Node.ELEMENT_NODE) {
Element cElmnt = (Element) cNode;
NodeList timeList = cElmnt.getElementsByTagName("time");
NodeList placeList = cElmnt.getElementsByTagName("place");
// init beans
ModelType t = new ModelType();
// (scroll down to see how getValue() is implemented)
t.setTime(getValue(timeList, 0));
t.setPlace(getValue(placeList, 0));
// add to list
posts.add(t);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private String getValue(NodeList fields, int index) {
NodeList list = fields.item(index).getChildNodes();
if (list.getLength() > 0) {
return list.item(0).getNodeValue();
} else {
return "";
}
}
you can, of course, extend this technique further (continue traversing deeper as you like) in order to match your needs.