PDA

View Full Version : Nested Model with XML Reader/Writer



margozzi
17 May 2011, 7:01 AM
I am unable to get a model to work with XML data that has hierarchy. It seems to me that the reader or writer at each level of the model hierarchy needs to be invoked. But that doe snot appear to be happening.

Here is the Data I am trying to consume:


<LongSeries>
<IndentifierList>CPU1,CPU2,CPU3,CPU4</IndentifierList>
<TotalCount>2</TotalCount>
<BaseTime>1304875831474</BaseTime>
<TimedLongs>
<T>0</T>
<V1>30</V1>
<V2>85</V2>
<V3>75</V3>
<V4>74</V4>
</TimedLongs>
<TimedLongs>
<T>2000</T>
<V1>60</V1>
<V2>75</V2>
<V3>8</V3>
<V4>77</V4> </TimedLongs> </LongSeries>


And here is my Model:


Ext.define("LongSeries", {
extend: "Ext.data.Model",
fields: [
{ name: 'IdentifierList', type: 'string' },
{ name: 'TotalCount', type: 'int' },
{ name: 'BaseTime', type: 'int' }
],
hasMany: 'TimedLongs',
proxy: {
type: 'rest',
url : '/rest/CpuStats?filter=Time(GT)0',
reader: {
type: 'xml',
record : 'TimedLongs'
}
}
});

Ext.define('TimedLongs', {
extend: "Ext.data.Model",
fields: [
{ name: 'T', type: 'date' },
{ name: 'V1', type: 'int' },
{ name: 'V2', type: 'int' },
{ name: 'V3', type: 'int' },
{ name: 'V4', type: 'int' }
],
belongsTo: 'LongSeries',
proxy: {
type: 'rest',
reader: {
type: 'xml',
record : 'TimedLongs'
}
}
});
However, this doesn't work. I have tried every permutation and combination I
can think of with no luck. At this point I believe this to be a bug in the ExtJS code base.

eascanzano
18 Jun 2011, 1:23 PM
I agree. The EXT development team probably never tested this. If they believe it works please post a **working** example which includes CDATA and deep nesting.

I hate it work software does not work!!!

mrobinson
18 Jun 2011, 4:17 PM
Out of curiosity, have you tried this in Safari? I ran into an issue with XML Reader wherein it works in Safari but not Firefox

christophe.geiser
19 Jun 2011, 11:31 PM
Hi,
I don't think the current code is in a position to handle nested xml data (or at least, I could not figure out how this would be possible, given the current DOMQuery) - there are a few posts re this topic. I wrote a short extension (http://www.sencha.com/forum/showthread.php?137126-real-xpath-selector) allowing me to use xpath selectors on XML and handle nested data.

Cheers and good luck with version 4.x ...
C.

margozzi
20 Jun 2011, 12:21 PM
I have not tried safari. There is really no point as it must work with FF and IE. Safari is not a requirement for us.

I think Sencha could make it work if they allowed for setting a read/writer at each level of the nexted model. It is pretty apparent that XML is a second class citizen, but they do claim to support it. Thus I have marked it a bug. Unfortunately this is the first traffic on this bug in quite some time. And none of it has been from Sencha. I am thinking they are only able to keep up with customers that paid for support. We have not yet signed up for support.

I will have a look at the code that you wrote. Thanks.

eascanzano
21 Jun 2011, 7:54 AM
Hi All,

By debugging the 4.0.1 code I actually figured this out - and it works! Here it is, first the xml, then the code.



<?xml version="1.0" encoding="UTF-8"?> <dataset> <row id="0" name="Ext.chart.Tip" javaclass="Behavior Standard Component" project="Coriolis" inactive="false" comments="" module="" repository="com.coriolis"> <listeners> </listeners> <clientMethods> </clientMethods> <configs> <config behaviorxml_id="0" id="0" name="id" inactive="false" comments="" module="" repository="com.coriolis"> <configScript> <![CDATA[<% return "'" + coriolis.getActiveObject().getUniqueID() + "'";%>]]> </configScript> </config> <config behaviorxml_id="0" id="1" name="UIComponentName" inactive="false" comments="" module="" repository="com.coriolis"> <configScript> <![CDATA[<% return "'" + coriolis.getCurrentComponent().getName() + "'";%>]]> </configScript> </config> </configs> </row> <row id="1" name="Ext.chart.axis.Abstract" javaclass="Behavior Standard Component" project="Coriolis" inactive="false" comments="" module="" repository="com.coriolis"> <listeners> </listeners> <clientMethods> </clientMethods> <configs> <config behaviorxml_id="1" id="0" name="id" inactive="false" comments="" module="" repository="com.coriolis"> <configScript> <![CDATA[<% return "'" + coriolis.getActiveObject().getUniqueID() + "'";%>]]> </configScript> </config> <config behaviorxml_id="1" id="1" name="UIComponentName" inactive="false" comments="" module="" repository="com.coriolis"> <configScript> <![CDATA[<% return "'" + coriolis.getCurrentComponent().getName() + "'";%>]]> </configScript> </config> </configs> </row> .....
</dataset>



Ext.define('Coriolis', {
});
var Coriolis = new Coriolis({});

Coriolis.behaviors = new Object();
Coriolis.displaytemplates = new Object();

// ***************************************************************************************
Ext.define('Config', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', mapping: '@id'},
{name: 'behaviorxml_id', mapping: '@behaviorxml_id'},
{name: 'name', mapping: '@name'},
{name: 'script',
convert: function(value, record){
if (record.raw != null) {
var cdata = Ext.DomQuery.selectNode('configScript', record.raw);
for(var i = 0, len = cdata.childNodes.length; i < len; i++){
var childNode = cdata.childNodes[i];
if(childNode.nodeType == 4){
return childNode.textContent || childNode.innerText || '';
}
}
return null;
}
}
}
]
});

Ext.define('Lstnr', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', mapping: '@id'},
{name: 'behaviorxml_id', mapping: '@behaviorxml_id'},
{name: 'name', mapping: '@name'},
{name: 'script',
convert: function(value, record){
if (record.raw != null) {
var cdata = Ext.DomQuery.selectNode('listenerScript', record.raw);
for(var i = 0, len = cdata.childNodes.length; i < len; i++){
var childNode = cdata.childNodes[i];
if(childNode.nodeType == 4){
return childNode.textContent || childNode.innerText || '';
}
}
return null;
}
}
}
]
});

Ext.define('ClientMethod', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', mapping: '@id'},
{name: 'behaviorxml_id', mapping: '@behaviorxml_id'},
{name: 'name', mapping: '@name'},
{name: 'script',
convert: function(value, record){
if (record.raw != null) {
var cdata = Ext.DomQuery.selectNode('clientModelScript', record.raw);
for(var i = 0, len = cdata.childNodes.length; i < len; i++){
var childNode = cdata.childNodes[i];
if(childNode.nodeType == 4){
return childNode.textContent || childNode.innerText || '';
}
}
return null;
}
}
}
]
});

Ext.define('BehaviorXML', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', mapping: '@id'},
{name: 'name', mapping: '@name'},
{name: 'javaclass', mapping: '@javaclass'}
],
associations: [{
type: 'hasMany',
model: 'Config',
primaryKey: 'id',
foreignKey: 'behaviorxml_id',
autoLoad: false,
associationKey: 'configs',
reader: {
type : 'xml',
model: 'Config',
record: 'config'
}
},
{
type: 'hasMany',
model: 'Lstnr',
primaryKey: 'id',
foreignKey: 'behaviorxml_id',
autoLoad: false,
associationKey: 'listeners',
reader: {
type : 'xml',
model: 'Lstnr',
record: 'listener'
}
},
{
type: 'hasMany',
model: 'ClientMethod',
primaryKey: 'id',
foreignKey: 'behaviorxml_id',
autoLoad: false,
associationKey: 'clientMethods',
reader: {
type : 'xml',
model: 'ClientMethod',
record: 'clientMethod'
}
}
],
proxy: {
type: 'ajax',
url : '/Coriolis/Main/md/realm1/Developer/Behavior',
reader: {
type: 'xml',
root: 'dataset',
record: 'row'
}
}
});

var behaviorStore = new Ext.data.Store({
model: 'BehaviorXML'
});

behaviorStore.load({
callback: function() {
var i = 0;
for (i = 0;i<this.getCount();i++) {
var behavior = this.getAt(i);

var o = new CBehavior({});
o.setName(behavior.get('name'));

behavior.configs().each(function(config) {
var c = new CConfig({});
c.setName(config.get('name'));
c.setScript(config.get('script'));

o.addConfig(c);
});
Coriolis.behaviors[o.getName()] = o;
}
}
});