PDA

View Full Version : Advanced XML help



nicosk
23 Jul 2010, 3:17 AM
<Match id="681769">
<Home name="GUARANI CAMPINAS"/>
<Away name="CEARA"/>
<Results>
<Result id="1" name="CURRENT" value="1-1"/>
<Scorers>
<Scorer name="ERNANDES" team="3482" time="54"/>
<Scorer name="XAVIER" team="9971" time="75"/>
</Scorers>
</Results>
</Match>


How can i get the scorers as an array. They have the same node name.

My root node is <MATCH> as you can see

Regards,
Nicos

P.S. Sorry for the "Advanced" in the header.It was a mistake and i Can't change it now :)

Animal
23 Jul 2010, 4:03 AM
Are you loading a Store? I can only assume so.

Try a Field convert method.

Condor
23 Jul 2010, 6:17 AM
You need 2 XML readers, on to read matches and another one to read scorers (which is used in the convert function of the scorers field of the first reader).

Animal
23 Jul 2010, 6:32 AM
Wouldn't it be simpler just to use DomQuery directly in the convert?



{ mapping: 'Scorers', convert: function(v, el) {
var result = [],
scorers = Ext.DomQuery.select(el, 'Scorer');
for (var i = 0; i < scorers.length; i++) {
result.push(Ext.DomQuery.selectValue(scorers[i], '@name'));
}
return result;
}}


do if you wanted an Array of names?

Obviously if you wanted an Array of Objects containing



{
name: 'ERNANDES',
team: 3482,
time: 54
}


It would be a little different but same principle. Simpler than having 2 Readers.

Condor
23 Jul 2010, 7:03 AM
Using two readers:

var reader = new Ext.data.XmlReader({
record: 'Match',
idProperty: '@id',
fields: [
{name: 'id', mapping: '@id', type: 'int'},
{name: 'homeName', mapping: '> [email protected]'},
{name: 'awayName', mapping: '> [email protected]'},
{name: 'resultId', mapping: '> Results > [email protected]', type: 'int'},
{name: 'resultName', mapping: '> Results > [email protected]'},
{name: 'resultValue', mapping: '> Results > [email protected]'},
{name: 'scorers', convert: (function(){
var reader2 = new Ext.data.XmlReader({
record: '> Results > Scorers > Scorer',
fields: [
{name: 'name', mapping: '@name'},
{name: 'team', mapping: '@team', type: 'int'},
{name: 'time', mapping: '@time', type: 'int'}
]
});
return function(v, n) {
return reader2.readRecords(n).records;
};
})()}
]
});
(doesn't look that bad does it?)

Animal
23 Jul 2010, 7:26 AM
Quite neat actually! :)

muncher
23 Jul 2010, 12:30 PM
this one is really cool. Thanks. But I am not sure how to access it ..
I mean would be like Match.scorers[i].name ?


Ah.. how do I debug ? I mean I want to get to a point where it actually is unwinding the records. I mean ultimately it makes call to say for example the XMLReader in the extjs library, how do I break in XMLReader using firebug ? Just want to look at the object and how it looks or what properties it got etc. .. making my life a bit easier and so your

muncher
23 Jul 2010, 12:46 PM
the more i ask more i solve and more problems.


So i got hold of looking inside code and getting somewhat better understanding of what is going on.

So now I have template defined as -


tpl : new Ext.Template(
'<b>homeName:</b>{homeName}<br>',
'<b>awayName:</b>{awayName}<br>',
'<b>Scorers:</b>{scorer[0].data.name}<br>',
)
});



This is for the row expander plugin for gridpanel. In the above case, homeName, awayName works fine. But -
1. I want iterate over scorers
2. The template doesn't recognize scorer[0].data.name as a field but as a string.

How do I make template to read nested records ?

muncher
23 Jul 2010, 1:30 PM
Xtemplate \m/



'<table>',
'<tpl for="scorers">',
'<tr><td>{values.data.name}</td></tr>',
'</tpl></table>',

kortovos
27 Sep 2010, 11:09 PM
Is this also possible for Sencha Touch? And could you combine this with a model?

jeffj
13 Oct 2010, 3:14 PM
I have also been trying to get nested records to work with templates on Sencha touch. I'm afraid I might just have to build my own array.

Animal
13 Oct 2010, 9:15 PM
I would think it is quite possible. You might just have to experiment a bit with it, step through with the debugger and examine what the code is doing to determine any difference needed.

kortovos
18 Oct 2010, 2:35 AM
Doesn't the use of 2 readers mean that the source will be read 2 times?

I am currently trying to create something simular for touch, but since I am getting xml data from a Ajax proxy and not a regular xml file is creating difficulties.

Condor
18 Oct 2010, 3:44 AM
No. The second reader is only used to select values from the XML node that represents the record in the first reader.

kortovos
18 Oct 2010, 4:59 AM
Could the approach of two readers also work, not with attributes, but with elements?


<Scorers>
<Scorer>
<name>ERNANDES</name>
<team>34482</team>
<time>54</time>
</Scorer>
<Scorer>
<name>XAVIER</name>
<team>9971</team>
<time>75</time>
</Scorer>
</Scorers>

Using two readers:

var reader = new Ext.data.XmlReader({
record: 'Match',
idProperty: '@id',
fields: [
{name: 'id', mapping: '@id', type: 'int'},
{name: 'homeName', mapping: '> [email protected]'},
{name: 'awayName', mapping: '> [email protected]'},
{name: 'resultId', mapping: '> Results > [email protected]', type: 'int'},
{name: 'resultName', mapping: '> Results > [email protected]'},
{name: 'resultValue', mapping: '> Results > [email protected]'},
{name: 'scorers', convert: (function(){
var reader2 = new Ext.data.XmlReader({
record: '> Results > Scorers > Scorer',
fields: [
{name: 'name', mapping: '@name'},
{name: 'team', mapping: '@team', type: 'int'},
{name: 'time', mapping: '@time', type: 'int'}
]
});
return function(v, n) {
return reader2.readRecords(n).records;
};
})()}
]
});(doesn't look that bad does it?)

Condor
18 Oct 2010, 5:06 AM
Just remove the @ from the mapping (so it selects an element with that name instead of an attribute).

kortovos
18 Oct 2010, 5:26 AM
I presume that when you would do :

return function(v, n) {
console.log(v);
return reader2.readRecords(n).records;
};


That the record that is displayed by 'console.log(v)' already contains the scorers.

Condor
18 Oct 2010, 5:42 AM
'v' is a value - not usable in this case.

'n' is the 'Match' XML node from which you can locate the Scorers.

kortovos
18 Oct 2010, 5:43 AM
my apologies, I meant to ask if 'n' contained the 'scorers'.

Condor
18 Oct 2010, 5:54 AM
Yes, but in an unusable form. You need to use the second 'n' argument.

kortovos
18 Oct 2010, 6:00 AM
Then I can probably not use this method in combination with Sencha Touch and a store, because when I do:

console.log(n)It doesn't contain the needed data.

Condor
18 Oct 2010, 6:07 AM
Just checked Sencha Touch, but it too passes the XML node as the second argument.

kortovos
19 Oct 2010, 2:54 AM
I have found a way, though it is not as elegant as Condor's solution. But it works.

I use a store to read the matches. Once they are read, I use the '((store.getProxy()).getReader()).xmlData' along with a xml reader to get certain components (like 'scorers') which weren't inserted into the model instance of 'Match' , extract them and put them into another store. (or you could of course insert it as an array into the model instance of 'Match').

vallavan.s
8 Dec 2010, 9:46 PM
<Result>
<Table>
<logid>1111</logid>
<description>xxxxxxxxxxx</description>
<TaskID>4444</TaskID>
<EventType>Insert </EventType>
<LogDetails />
<processtime>Nov 23 2010 12:23PM</processtime>
</Table>
<Table>
<logid>2222</logid>
<description>xxxxxxxxxxx</description>
<TaskID>4444</TaskID>
<EventType>Insert </EventType>
<LogDetails />
<processtime>Nov 23 2010 12:23PM</processtime>
</Table>
<Table>
<logid>3333</logid>
<description>xxxxxxxxxxx</description>
<TaskID>4444</TaskID>
<EventType>Insert </EventType>
<LogDetails />
<processtime>Nov 23 2010 12:23PM</processtime>
</Table>
<Table1>
<RequestId>111</RequestId>
<RequestType>Login </RequestType>
<PId>6666</PId>
<ResponseStatus>Succeed</ResponseStatus>
</Table1>
<Table1>
<RequestId>111</RequestId>
<RequestType>Task </RequestType>
<PId>6666</PId>
<ResponseStatus>Failed </ResponseStatus>
</Table1>
<Table1>
<RequestId>111</RequestId>
<RequestType>Logout</RequestType>
<PId>6666</PId>
<ResponseStatus>Succeed</ResponseStatus>
</Table1>
<Table2>
<PId>4485</PId>
<AccountNumber>dgdfgdfg</AccountNumber>
<RequestXML></RequestXML>
<ResponseXML></ResponseXML>
<TaskId>4444</TaskId>
<EventType>Insert</EventType>
</Table2>
</Result>

Condor
8 Dec 2010, 11:49 PM
I need to get the following to data store.... How to do this?

That's not enough information. You also need to tell use which fields you want in this store.

vallavan.s
9 Dec 2010, 12:23 AM
Hi Condor!
Actually I need to display 3 grids in a window. I'm working in .net.
I'm getting data from database to dataset. I'm directly converting the dataset to XML by calling the dataset.WriteXML().

So I'm getting the above XML. That contains 3 tables. Table, Table1, Table2

I want to bind each table to each grid. So I'm using data store t o call an url and trying to read the above with xml reader. I have seen your post regarding advance xml reading with nested reader. I have tried to implement. But failed.

If I get the solution that will be great help.

Condor
9 Dec 2010, 12:25 AM
For this you would create 3 stores, each with it's own reader (with a different 'record' config option).

Next, you would load one of the stores and with the result load the other stores, e.g.

store1.load({
callback: function(){
store2.loadData(store1.reader.xmlData);
store3.loadData(store1.reader.xmlData);
}
});

vallavan.s
9 Dec 2010, 12:37 AM
So If we do this whether it will make ajax call three times?

Condor
9 Dec 2010, 12:42 AM
So If we do this whether it will make ajax call three times?

This will do one AJAX request and use the data for 3 stores.

vallavan.s
9 Dec 2010, 12:48 AM
Thanks a lot Condor! I got it....... I'm very happy.... I'm striving for this from yesterday.

squalo
10 Feb 2011, 3:36 AM
I'm not the lucky man, like the combatants above ;)

I try to load this XML data:


<?xml version='1.0' encoding='UTF-8'?>
<CONFIGURATION>
<PLATFORM name="xx" version="4.0" reference="xx.xml">
<PROJECT name="XX246" provider="XX" index="P" prefix="XX" postfix="" offset="000" count="3" IPv4_first="10.1.71.1" IPv4_last="10.1.71.250">
<ITEM number="246000" version="29" IPv4="10.1.71.1" LastChange="28.01.2011" Author="" Size="10">
<CONFIG value_1="$1234abcd" value_2="$1234abcd" value_3="$1234abcd" value_4="$1234abcd" value_5="$1234abcd" value_6="$1234abcd" value_7="$1234abcd" value_8="$1234abcd" value_9="$1234abcd" value_10="$1234abcd">2e4ef862b21e4f5f252fa09d07ebb7d8</CONFIG>
</ITEM>
<ITEM number="246001" version="10" IPv4="10.1.71.9" LastChange="28.01.2011" Author="squalo" Size="10">
<CONFIG value_1="$1234abcd" value_2="$1234abcd" value_3="$1234abcd" value_4="$1234abcd" value_5="$1234abcd" value_6="$1234abcd" value_7="$1234abcd" value_8="$1234abcd" value_9="$1234abcd" value_10="$1234abcd">ce89ec30ddbd0829c39e40e36708133b</CONFIG>
</ITEM>
</PROJECT>
<PROJECT name="XX285" provider="XX" index="U" prefix="XX" postfix="" offset="000" count="3" IPv4_first="10.1.73.1" IPv4_last="10.1.73.250">
<ITEM number="285001" version="9" IPv4="10.1.73.1" LastChange="28.01.2011" Author="" Size="10">
<CONFIG value_1="$1234abcd" value_2="$1234abcd" value_3="$1234abcd" value_4="$1234abcd" value_5="$1234abcd" value_6="$1234abcd" value_7="$1234abcd" value_8="$1234abcd" value_9="$1234abcd" value_10="$1234abcd"></CONFIG>
</ITEM>
<ITEM number="285002" version="10" IPv4="10.1.73.9" LastChange="28.01.2011" Author="" Size="10">
<CONFIG value_1="$1234abcd" value_2="$1234abcd" value_3="$1234abcd" value_4="$1234abcd" value_5="$1234abcd" value_6="$1234abcd" value_7="$1234abcd" value_8="$1234abcd" value_9="$1234abcd" value_10="$1234abcd"></CONFIG>
</ITEM>
</PROJECT>
</PLATFORM>
</CONFIGURATION>


and I was happy while condor wrotes that it is possible to use more than one XMLReader.
(Because I have several projects within several items)
So I tried this (in my ignorant awareness)




var store = new Ext.data.XmlStore({
// load using HTTP
url: '../config/configuration.xml',
record: 'PLATFORM',
id: '@name',
fields: [
// set up the fields mapping into the xml doc
// The first needs mapping, the others are very basic
{name: 'Platform', mapping: '@name'},
{name: 'PlatformVersion', mapping: '@version'},
{name: 'PlatformRef', mapping: '@reference'},
{name: 'projects', convert: (function(){
var store2 = new Ext.data.XmlStore({
record: '> PROJECT',
fields: [
{name: 'Project', mapping: '@name'},
{name: 'Provider', mapping: '@provider'},
{name: 'NFSIndex', mapping: '@index'},
{name: 'Prefix', mapping: '@prefix'},
{name: 'Postfix', mapping: '@postfix'},
{name: 'Offset', mapping: '@offset', type: 'int'},
{name: 'Digits', mapping: '@count', type: 'int'},
{name: 'RangeIPv4Begin', mapping: '@IPv4_first'},
{name: 'RangeIPv4End', mapping: '@IPv4_last'},
]
});
return function(v, n) {
console.log(n);
return store2.readRecords(n).records;
};
})()},
{name: 'items', convert: (function(){
var store3 = new Ext.data.XmlStore({
record: '> ITEM',
fields: [
{name: 'Number', mapping: '@number'},
{name: 'Version', mapping: '@version', type: 'int'},
{name: 'IPv4', mapping: '@IPv4'},
{name: 'LastChange', type:'date', dateFormat:'d.m.Y', mapping: '@LastChange'},
{name: 'Author', mapping: '@Author'},
{name: 'Config1', mapping: '> [email protected]_1'},
{name: 'Config2', mapping: '> [email protected]_2'},
{name: 'Config3', mapping: '> [email protected]_3'},
{name: 'Config4', mapping: '> [email protected]_4'},
{name: 'Config5', mapping: '> [email protected]_5'},
{name: 'Config6', mapping: '> [email protected]_6'},
{name: 'Config7', mapping: '> [email protected]_7'},
{name: 'Config8', mapping: '> [email protected]_8'},
{name: 'Config9', mapping: '> [email protected]_9'},
{name: 'Config10', mapping: '> [email protected]_10'},
{name: 'ConfigCheck', mapping: '> CONFIG'},
]
});
return function(v, n) {
console.log(n);
return store3.readRecords(n).records;
};
})()}
]
});


but nothing happens. Neither loading, nor any output on the firebug console. Even no errors are rasing there.(I already included ext-all-debug.js)
Any ideas what I'm doing wrong?

thx in advance

Condor
10 Feb 2011, 6:09 AM
I assume you want items inside projects?

And my example uses nested XmlReaders and not XmlStores!

squalo
10 Feb 2011, 7:00 AM
Yes.

And unfortunately I need the option/posssibility in ExtJS to change each attribute or value in this XML file.
So I thought, that 'only' XMLReader would not help here.

Are there any remedies to this?

Thx in advance

squalo
10 Feb 2011, 8:06 AM
Btw:

Assuming I could read now the nested tags with XMLReaders.
How can I put them into the grid?


// Platforms
var colPlatform = new Ext.grid.ColumnModel({
defaults: {
sortable: false,
menuDisabled: true,
renderer: LineHeight,
},
columns: [
{header: "Project", width: 120, dataIndex: 'projects[].Project', sortable: false, },
]
});


What do I have to write to 'dataIndex:' ? (The code above is only guessing - what else)

Furtheron appreciating any hints.

Condor
11 Feb 2011, 1:51 AM
This is nested data! You need a master+child grid or a treegrid to display this.

squalo
11 Feb 2011, 2:33 AM
I have just 2 grids running for that. But how could I change them for Master+Child?
With a Listener?
(At the moment both have 'store: store,' )

Do you could give perhaps kindly an example?

Thx.

Condor
21 Feb 2011, 5:50 AM
I don't have an example at hand, but the two grids wouldn't have the same store.

One would have a store with a reader that reads the top level records and the second store would have a reader that reads the second level records.

When a row is selected in the first grid, you load the second grid with the xml node of the selected record.

squalo
21 Feb 2011, 7:18 AM
OK. But how can I get the XMLDocument of this certain node?

If I use reader.xmlData of the first store I got them all!


Btw.: Regarding the amount of your posts here, you must have invent the word 'help' ;)
(really appreciating)

Condor
21 Feb 2011, 7:30 AM
Any record created by an XmlReader has a 'node' property that holds the XML node used to create the record.

You can use this node to load the second store.

squalo
21 Feb 2011, 7:43 AM
You made my day!!!

Thx a lot.