Using SmartGWT 2.3, Firefox 3.6.12.
Hi, I am trying to find a way of binding an XML record (returned from our database as a String) to a dynamic form and some grids for editing, then returning back the modified document to be saved.
I've been tinkering, and searching the forum and documentation for days without finding a solution, so here goes...
Currently, I'm trying the approach of creating a Document object built from the XML string in the DataSource and setting it as the data object in the DataSource, but from debugging, it isn't being translated to JSON in the way I was expecting. Simple text nodes seem to convert and render correctly, but any element with attributes is converted into a JSON object and the actual node text is ommitted.
I've stripped down the problem to a smaller example to demonstrate what I'm seeing. Hopefully someone can shed some light or point me in the right direction:
Client - (simple DynamicForm in example, but full solution requires ListGrid too for displaying repeating elements in the XML...)
DataSource class - I've removed the handlers/DAOs and just have a static String representing a very cut-down version of the XML.
I create a Document object using the DocumentBuilder and have verified it's contents by traversing the nodes and outputing what I find.
DataSource config file:
The valueXPath declarations seem to be causing the DataSource to create JSON object structures for 'artist', 'artistID' and 'artistSource' fields. However none of these objects contain the actual XML node text. (Why?)
If I omit the valueXPath value from each field, the DataSource creates just one object 'artist' with two attributes 'id' and 'source', (which is more what I would expect) but again, no data for the actual tag text.
Does this mean the xpath values in the DataSource config are irrelevant? I can see the client just maps the JSON fields using the name? (Which is why "title" gets rendered correctly and the others get rendered as "[object Object]"). But if I change the DataSource config to set dataFormat="xml" or add a recordXPath="/product" statement, an error is thrown when the DataSource is initialized.
RPC Response when fetch is called with valueXPath values applied to fields in the config file:
I've tried a few variations on this theme, tweaking the DataSource config with various options with no success - my main question is, is this the right approach for this problem or not? If not, can anyone suggest an alternative approach that will allow us to easily pass a XML String/Document to the client, and get a (modified) String/Document back (preferably with examples!?) Will I have problems rendering elements in a ListGrid too?
If the general approach is correct, can anyone fill-in the blanks... what configuration do I need in my DataSource and how can I get my Document object to translate correctly? I've looked at the JSTranslater javadoc but calling toJS() on the Document object isn't yeilding the result I was expecting. i.e. it omits the text values of the tags that have attributes.
The javadoc states that
but what does it do with the actual tag text?
Many thanks for any pointers...
Hi, I am trying to find a way of binding an XML record (returned from our database as a String) to a dynamic form and some grids for editing, then returning back the modified document to be saved.
I've been tinkering, and searching the forum and documentation for days without finding a solution, so here goes...
Currently, I'm trying the approach of creating a Document object built from the XML string in the DataSource and setting it as the data object in the DataSource, but from debugging, it isn't being translated to JSON in the way I was expecting. Simple text nodes seem to convert and render correctly, but any element with attributes is converted into a JSON object and the actual node text is ommitted.
I've stripped down the problem to a smaller example to demonstrate what I'm seeing. Hopefully someone can shed some light or point me in the right direction:
Client - (simple DynamicForm in example, but full solution requires ListGrid too for displaying repeating elements in the XML...)
Code:
package com.nielsen.smartgwt.test.client; import com.smartgwt.client.data.DataSource; import com.smartgwt.client.widgets.form.DynamicForm; import com.smartgwt.client.widgets.form.fields.TextItem; import com.smartgwt.client.widgets.layout.VLayout; public class ExampleGUI { public ExampleGUI() { VLayout layout = new VLayout(); DynamicForm form = new DynamicForm(); TextItem txtArtistID = new TextItem("artistID", "Artist ID"); TextItem txtArtistSource = new TextItem("artistSource", "Artist Source"); TextItem txtArtist = new TextItem("artist", "Artist"); TextItem txtTitle = new TextItem("title", "Title"); form.setDataSource(DataSource.get("exampleDataSource")); form.setFields(txtArtistID, txtArtistSource, txtArtist, txtTitle); layout.addMember(form); form.fetchData(); layout.draw(); } }
I create a Document object using the DocumentBuilder and have verified it's contents by traversing the nodes and outputing what I find.
Code:
package com.nielsen.smartgwt.test.server; import java.io.StringReader; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.traversal.DocumentTraversal; import org.w3c.dom.traversal.NodeFilter; import org.w3c.dom.traversal.NodeIterator; import org.xml.sax.InputSource; import com.isomorphic.datasource.BasicDataSource; import com.isomorphic.datasource.DSRequest; import com.isomorphic.datasource.DSResponse; import com.isomorphic.js.JSTranslater; public class ExampleDataSource extends BasicDataSource { private static Log LOG = LogFactory.getLog(ExampleDataSource.class); private static DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); static { factory.setNamespaceAware(true); } private static String xmlHeader = "<?xml version='1.0' encoding='UTF-8'?>"; private static String xml = "<product id='101'>" + "<artist id='224' source='devAdmin'>Artist Name</artist>" + "<title>Some Title</title>" + "</product>"; /** * {@inheritDoc} */ @Override public DSResponse executeFetch(DSRequest request) throws Exception { LOG.debug("Executing FETCH"); DSResponse dsResponse = new DSResponse(); dsResponse.setDataSource(this); dsResponse.setSuccess(); dsResponse.setTotalRows(1); dsResponse.setStartRow(0); dsResponse.setEndRow(0); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new InputSource(new StringReader(xmlHeader+xml))); DocumentTraversal traversal = (DocumentTraversal) doc; NodeIterator iterator = traversal.createNodeIterator( doc.getDocumentElement(), NodeFilter.SHOW_ELEMENT, null, true); for (Node n = iterator.nextNode(); n != null; n = iterator.nextNode()) { LOG.debug("Name=" + ((Element) n).getTagName() + " : id=" + ((Element) n).getAttribute("id") + " : source=" + ((Element) n).getAttribute("source") + " : value=" + ((Element) n).getTextContent()); } JSTranslater t = JSTranslater.get(); t.enablePrettyPrinting(); LOG.debug("Doc to JS=" + t.toJS(doc)); dsResponse.setData(doc); return dsResponse; } // ... other methods omitted for brevity }
Code:
<DataSource ID="exampleDataSource" serverConstructor="com.nielsen.smartgwt.test.server.ExampleDataSource" > <fields> <field name="artistID" type="integer" valueXPath="artist[@id]" /> <field name="artistSource" type="text" valueXPath="artist[@source]" /> <field name="artist" type="text" valueXPath="artist"/> <field name="title" title="Title" type="text" valueXPath="title" /> </fields> </DataSource>
If I omit the valueXPath value from each field, the DataSource creates just one object 'artist' with two attributes 'id' and 'source', (which is more what I would expect) but again, no data for the actual tag text.
Does this mean the xpath values in the DataSource config are irrelevant? I can see the client just maps the JSON fields using the name? (Which is why "title" gets rendered correctly and the others get rendered as "[object Object]"). But if I change the DataSource config to set dataFormat="xml" or add a recordXPath="/product" statement, an error is thrown when the DataSource is initialized.
RPC Response when fetch is called with valueXPath values applied to fields in the config file:
Code:
//isc_RPCResponseStart-->[{endRow:0,totalRows:1,isDSResponse:true,invalidateCache:false,status:0,startRow:0,data:{title:"Some Title",artistID:{id:"224",source:"devAdmin"},artistSource:{id:"224",source:"devAdmin"},artist:{id:"224",source:"devAdmin"},id:"101"}}]//isc_RPCResponseEnd
If the general approach is correct, can anyone fill-in the blanks... what configuration do I need in my DataSource and how can I get my Document object to translate correctly? I've looked at the JSTranslater javadoc but calling toJS() on the Document object isn't yeilding the result I was expecting. i.e. it omits the text values of the tags that have attributes.
The javadoc states that
Code:
XML Elements (org.w3c.dom.Element) and XML Documents (org.w3c.dom.Document) are treated identically to XML found in <isomorphic:XML> tags in .jsps, that is, component definitions like <ListGrid .. /> become live SmartClient components, and any other Elements become JavaScript Objects, where each attribute or subelement becomes a JavaScript property.
Many thanks for any pointers...
Comment