TreeGrid XML data format description

TreeGrid v4.3

 

Basics

 

Individual attributes of XML tags are described in XML format reference.

TreeGrid uses XML structure to describe data rows and cols. The root tag is always <Grid>.

Immediate children of <Grid> tag are main tags and describe the parts of the grid: Communication (<IO>), Configuration (<Cfg>), Defaults (<Def>), Left panel (<Panel>), Columns (<LeftCols>, <Cols>,<RightCols>), Header (<Header>), Rows (<Head>, <Body>,<Foot>), Toolbar (<Toolbar>), Configuration menu (<MenuCfg>), Pager (<Pager>), Language settings (<Lang>).

Order of main tags is optional. Not all main tags must be present, most of their attributes are pre-defined in required files Defaults.xml and Text.xml.

Required main tags are <Cols> and <Body>, these tags must contain at least one children (TreeGrid must contain at least one variable column and one page).

 

If tags are defined in more files, their attributes and children are merged. Existing attributes are overwritten by new value. Defaults (<D>) and columns (<C>) tags are merged by Name attribute. Fixed rows (<I>) are merged by id. Other tags are single and are merged by tag name.

Pages (<B>) and variable rows (<I>) are not merged, just added, even if they are the same id – this will cause an error. It is due performance reason.

Data are loaded in this order: Text.xml + Bonus, Defaults.xml + Bonus, Layout + Bonus, Data + Bonus.

 

Formats

 

TreeGrid accepts data in XML format. The XML format can use one of four sub-formats: Internal, DTD, Short, Extra short. These formats differ in speed of processing, data length and DTD standard compatibility. The format structure differs in storing cell values and cell and row attributes. This affects tags <D>, <I> and <Header> only.

This XML format is not compatible with XML format from TreeGrid v2.x. The CSS format from TreeGrid v1.x and v2.x has been abandoned.

 

Internal format     Preferred format. This format uses TreeGrid as internal format to store data. Thus if you use JavaScript API to browse TreeGrid data on client, the data is in internal format. The format is fast to process and is shorter then DTD format. It can be generated and processed on server side by standard XML parser but without DTD validation and cannot use standard function to locate rows by their ids. You cannot use predefined DTD, but you can define you own DTD for your data.

Internal format stores cell values as row attributes named as column name. And cell attributes stores in row attributes named as column name joined with attribute name.

This format is also used in all samples and in TreeGrid server.

Example:

<Grid><Body><B>

<I id='r1' c1='1' c2='xx' CanDelete='0'>

  <I id='r11' c2='xx-aa' c3='10' CanEdit='0' c2CanEdit='1'/>

  <I id='r12' c2='xx-bb' c3='20'/>

</I>

<I id='r2' c1='2' c2='yy'>

  <I id='r21' c1='10' c2='yy-aa' Calculated='1' c3Formula='c1*2' />

</I>

</B></Body></Grid>

 

 

DTD format        It is largest and has slowest processing. Use it for short data that need to be generated and processed on server side by standard XML parser with DTD validation and using getElementById (or similar) method to find row by id.

DTD format contains each cell data and settings in separate tag <U>. This tag has attribute N with column name and can have attribute V with cell value and other attributes named as cell parameters.

This is recommended format for small grids.

Example:

<Grid><Body><B>

<I id='r1' CanDelete='0'><U N='c1' V='1'/><U N='c2' V='xx'/>

  <I id='r11' CanEdit='0'><U N='c2' V='xx-aa' CanEdit='1'/><U N='c3' V='10'/></I>

  <I id='r12'><U N='c2' V='xx-bb'/><U N='c3' V='20'/></I>

</I>

<I id='r2'><U N='c1' V='2'/><U N='c2' V='yy'/>

  <I id='r21' Calculated='1'><U N='c1' V='10'/><U N='c2' V='yy-aa'/><U N='c3' Formula='c1*2'/></I>

</I>

</B></Body></Grid>

 

 

Short format            It is shorter then internal or DTD format and is fast to process. It can be generated and processed on server side by standard parser with DTD validation and using getElementById (or similar) method to find row by id, same as DTD format. But cell values and attributes are stored as text node and needs another parsing on server side.

Short format stores cell values and row and cell attributes except id attribute in text node in row according to predefined Par tag. Attribute names in text use Internal format naming.

Text node has this format: “|par|attr1|attr2|...|attrN”, where “|” is chosen character that is not present in any attribute value. par is name of <P Name=’’> tag. And next are separated values of attributes in <P List=’’>. Count of attributes must be the same as count of attributes in List. If any attribute value is missing, just leave the space empty, but separator must be present.

Don’t append any empty characters to node texts with this format. Always append enclosing tag or first child’s tag immediately after the text.

This is recommended format for large grids.

Example:

<Grid>

<Par>

<P Name='N' List='CanDelete,c1,c2'/>

<P Name='D' List='Calculated,CanEdit,c1,c2,c2CanEdit,c3,c3Formula'/>

</Par>

<Body><B>

<I id='r1'>|N||1|xx<I id='r11'>|D|0|0||xx-aa|1|10|</I>

  <I id='r12'>|D||||xx-bb||20|</I>

</I>

<I id='r2'>|N|1|2|yy<I id='r21'>|D|1||10|yy-aa|||c1*2</I>

</I>

</B></Body></Grid>

 

 

Extra short format It is the shortest and is the fastest to process. It can be generated and processed on server side by standard XML parser with DTD validation, but without access rows by their id attribute. But cell values, row and cell attributes and immediate leaf children row’s attributes and cells are stored as text node, therefore it needs another parsing on the server side.

Extra short format stores row’s attributes, cell values and attributes and attributes of all immediate children data rows (rows without children) in text node. Attribute names in text use Internal format naming. It can be used also for list of pages when server paging used.

The text node has this format: “|par|attr1|attr2|...|attrN|par|count|attr1-1|...|attr1-N|attr2-1|...|attr2-N|... ...|attrM-1|...|attrM-N”, where the first part is the same as in Short format, but next is par – name of <P Name=’’> for immediate children without any their children, count is count of the children and next is two-dimensional table of attribute values, where N is from 1 to length of List and M is from 1 to count. Parameters can now include even id parameter.

If the main row has no attributes and first part is empty, just let it empty, like “||par|count|...” – two starting separators.

If there are too many children (>1000, this has sense for list of empty pages for very large grids), is possible to use another separator to divide children to sections. This speeds up data parsing in IE. You can use “~|par|attr1|attr2|...|attrN|par|count|~attr1-1~...~attr1-N~attr2-1~...~attr2-N~... |~ ...~attrM-1~...~attrM-N”. The ~ is second separator, it is usually used for every 100 children.

Don’t append any empty characters to node texts with this format. Always append enclosing tag immediately after the text.

This is recommended format for list of pages for very large grids with more then 500 pages.

 

Example:

<Grid>

<Par>

<P Name='N' List='id,CanDelete,c1,c2'/>

<P Name='D' List='id,Calculated,CanEdit,c1,c2,c2CanEdit,c3,c3Formula'/>

</Par>

<Body><B>

<I>|N|r1||1|xx|D|2||r11|0|0||xx-aa|1|10||r12||||xx-bb||20|</I>

<I>|N|r2|1|2|yy|D|1||r21|1||10|yy-aa|||c1*2</I>

</B></Body></Grid>

 

Example for list of pages when server paging used:

<Grid>

<Par>

<P Name='B' List='Name,Csum'/>

</Par>

<Body>~||B|10000|~P1~43~P2~76~P3~45~ ... ~P99~65|~P100~23~P101~56~ ... ~P199~34|~P200~89~ ... ~P9999~123</Body>

</Grid>

 

 

 

 

Names and IDs

 

Rows are identified by attribute id (both characters lowercase!). If this attribute is not set, row cannot be identified and its changes cannot be updated to server. Therefore every editable row needs to have set its id. All rows ids must be unique among all row ids inside one grid. The id is not used in JavaScript API to access rows. But you can use function GetRowById.

 

Columns are identified by attribute Name. Every column must have set this attribute. The Name identifies column and row’s cells. Under this name are row’s cells in this column set and accessed. All column names must be unique among all column names inside one grid. Under this name saves column its configuration to the cookies. If you change any column name, you need to increment <Cfg> attribute Version to clear old configuration. In JavaScript API, cell is accessed by column name.

! Attention ! Column names must not interfere with row’s attribute names, like Def, Kind or Deleted !

The best way is to name columns as letter ‘A’, ‘B’ or ‘a’, ‘b’. There is no interference and data length is short.

 

Defs (default rows or columns) are identified by attribute Name. Every def must have set this attribute. The rows that use values from this default points to the default row by its attribute Def, with value of def Name. The default column must have NameC”. The default row for all rows and defs has NameR”. If fixed (head or foot) row has not set Def attribute, it uses def with NameFixed”. The def can also point to another def by Def attribute.

 

All ids and names are case sensitive and can contain lower and uppercase letters (a-z, A-Z) and character “_”. Cannot start with digit but can contain digits (0-9). Any other characters are forbidden.

 

Defaults

 

Every row <I> has predefined attribute values in its default row <D>. The values from <D> are used when the row <I> has some attribute not set. If row has attribute set to empty value, the default value is not used.

Using defaults helps you to reduce data size and also to control adding and moving rows. But using defaults is not required.

Using defaults is good especially for trees with different levels, at least to differentiate tree nodes and data rows.

 

Defaults <D> are identified by their attribute Name. By this Name string are referenced from rows or other defaults by attributes Def or CDef. See Names and ids.

 

Def attribute specifies default for the row itself.

You can use Def attribute even in <D> tag to reference another <D>. This means that you define <I> that references to its <D> that references to another <D>, that ...

If you don’t set Def attribute for any <D> or <I> tag the default is always <D Name=”R”>. Only for fixed rows is predefined <D Name=”Fixed”> that, of course, references “R” default too. This means that any attribute value not set in branch of <I> and <D> tags is at last read from “R” default.

Pay attention to cross-references among <D> tags.

 

CDef attribute specifies default for all immediate children rows, but only if they have not set their own Def attribute.

When dragging rows to children of the row, the parent row can accept only children rows with the same default as the parent row’s CDef.

When adding rows to children of the row, the new row will implicitly have default the same as parent rows’ CDef.

You can use CDef attribute even in <D> tag to predefine CDef attribute for all rows that use this default (the CDef attribute does not concern <D> tag itself, unlike Def attribute).

The CDef attribute can be also set in tag <Header>, this specifies default for all root rows. In this case (but in this case only), <Header> acts as parent for all variable root rows, including adding and dragging rows to root.

 

You can specify to row which default to use by many ways, all can be done in every case, but some are better for some cases and some for other cases.

Using Def attribute only is simpler but by CDef attribute you can control more. Remember, CDef attribute you can set even in <D> and <Header> tags too.

 

If you don’t use any Def or CDef attributes, all variable rows will have default <D Name=“R”> and fixed rows <D Name=”Fixed”>. These <D> are defined in basic file Defaults.xml. It means, if you don’t need to use defaults, you need not do it. You can change attributes of “R” or “Fixed” if you use <D> tag with this name in your data. New attributes you specify are merged or overwrite attributes specified in Defaults.xml => you don’t need to edit this file for every new grid.

 

Very large tables

 

There are few advices how to use TreeGrid for grids with more then about 10 000 root rows. It is not related to huge trees, the tree can handle unlimited count of rows.

All these advices are used only to speed up rendering and using TreeGrid, they do not concern about handling of such amount of rows, TreeGrid can handle unlimited rows count.

 

For grids with more then 10 000 rows always use server paging (<Cfg Paging=’3’/>). Your server script must provide data for grid’s pages. You can use TreeGrid server component to help you with this task. The TreeGrid server can do nearly all functions required in server paging as creating pages according to sorting and filter settings. Also pre-calculates aggregate functions. Saves changes returned from client. And more.

 

For grids with more then 50 000 rows use Extra short format to send list of pages. The TreeGrid server does it automatically.

If possible, use all page of the same width and don’t return rows count for every page, but set <Cfg PageLength and RootCount /> attributes. The TreeGrid server does it automatically.

Also increase <Cfg PageLength/> attribute according to count of columns in your grid. For 1 – 5 columns use 100, for 5-10 use 50 and for more columns use 30.

Also use <Cfg FastPages/> attribute. Set it to value about 100. Higher value speeds up initial rendering but can slow down work with the grid and vice versa.

 

For grids with more then 250 000 rows and all pages visible (<Cfg AllPages=’1’ />) use <Cfg PageLengthDiv/> attribute to reduce page size and all grid scroll height because some browsers have problems with too high scroll height. IE has problems with editing in tag with scroll height higher 5M pixels (about 277 000 rows of standard height). Mozilla has scrolling problems from about the same height.

Set PageLengthDiv to your rows count / 200 000. For 1 000 000 set it to 5.

 

For grids with more then 2 000 000 rows display only one page at once by using <Cfg AllPages=’0’ />. If you use configuration menu, set <MenuCfg AllPages=’0’/>. Also to suppress loading defaults for AllPages use AllPagesLap=’1’.

If you use TreeGrid server, remember that for such amount of rows it allocates about 400 MB memory. Of course, it does concern client browser memory consumption; it is independent on row count.

 

XML structure – download

 

Data sent from server to grid. Used when downloading data for empty grid or reloading all data for the grid or for body.

 

<Grid> (Root tag, can accept any count of introduced child tags in any order)

 

   <IO ... attributes with server response ... />

 

   <Img ... attributes with images setting ... />

 

   <Colors ... attributes with cell background color setting ... />

 

   <Cfg ... attributes with grid settings ... />

 

   <Def> ( list of default settings (tags <D>) for rows)

      <D Name='name of default' ... row attributes ... ... cell attributes and values in Internal format ... >

         <U Ncolumn name’ ... cell attributes and value in DTD format ... />

         ... more tags <U> for other cells, in DTD format ...

      </D>

      ... More tags <D> ...

   </Def>

 

   <Par> (list of prepared parameters for short formats)

      <P Name="list name" List="parameter names, comma separated"/>

   </Par>

 

   <Panel ... Attributes for left row panels settings ... />

 

   <LeftCols> ( Columns fixed to left side, still visible, can be empty)

      <C Name='column name' ... Attributes with column settings ... />

      ... more tags <C> for other columns ...

   </LeftCols>

   <Cols> (Variable columns, required, must contain at least one column)

      <C Name='column name' ... Attributes with column settings ... />

      ... more tags <C> for other columns ...

   </Cols>

   <RightCols> (Columns fixed to right side, still visible, can be empty)

      <C Name='column name' ... Attributes with column settings ... />

      ... more tags <C> for other columns ...

   </RightCols>  

 

   <Header ... Attributes with column titles (named as column names) and header row settings in Internal format ... >

      <U N='column name' V='column title' ... attributes with header row settings in DTD format ... />

      ... more tags <U> for other columns, in DTD format ...

   </Header>

 

   <Head> (List of top fixed rows, always visible, can be empty, rows cannot contain children rows)

      <I ... row attributes ... ... cell attributes and values in Internal format ... >

         <U Ncolumn name’ ... cell attributes and value in DTD format ... />

         ... more tags <U> for other cells, in DTD format ...

      </I>

      ... More tags <I> ...

   </Head>

 

   <Body> (List of all variable rows in pages, required, must contain at least one page, must not contain rows in root (only in pages))

      <B> (One page with rows, if pages are created automatically, can be only one with all rows)

          <I ... row attributes ... ... cell attributes and values in Internal format ... >

            <I ... row attributes ... ... cell attributes and values in Internal format ... >

                 <U Ncolumn name’ ... cell attributes and value in DTD format ... />

                 ... more tags <U> for other cells, in DTD format ...

               ... More tags <I>, with possible children tags I with possible children and so on – unlimited levels of tree ...

              </I>

            ... More tags <I> ...

             <U Ncolumn name’ ... cell attributes and value in DTD format ... />

             ... more tags <U> for other cells, in DTD format ...

          </I>

      ... More tags <I> ...

      </B>

      ... More tags <B> if data of pages are loaded on demand ...

   </Body>

 

   <Foot> (List of bottom fixed rows, always visible, can be empty, rows cannot contain children rows)

      <I ... row attributes ... ... cell attributes and values in Internal format ... >

         <U Ncolumn name’ ... cell attributes and value in DTD format ... />

         ... more tags <U> for other cells, in DTD format ...

      </I>

      ... More tags <I> ...

   </Foot>

 

   <Toolbar ... Attributes with settings for bottom toolbar ... />

   <MenuCfg ... Attributes with settings for dialog displayed for configuration ... />

   <Pager ... Attributes with pager settings ... />

 

   <Lang> (All language depended texts and formats)

      <Alert ... Attributes with plain text for alert dialogs .../>

      <Text ... Attributes with html text for messages and other use ... />

      <Toolbar ... Attributes with tool tips texts for toolbar buttons .../>

      <MenuCfg ... Attributes with menu item names and values ... />

      <Format ... Attributes with format texts and regional settings ... />

   </Lang>

 

</Grid>

 

XML structure – upload

 

Data sent from grid to server. Used when uploading changes to server.

Data sent from server to grid. Used when downloading changes done on server after uploading.

 

<Grid> (Root tag, can accept any count of introduced child tags in any order)

 

   <IO ... attributes with request settings... />

 

   <Changes> (list of changed rows)

      <I ... row attributes ... ... cell attributes and values in Internal format ... >

          <U Ncolumn name’ ... cell attributes and value in DTD format ... />

          ... more tags <U> for other cells, in DTD format ...

      </I>

   </Changes>

</Grid>

 

XML structure – request

 

Data sent from grid to server.

Used in request for:

a)       body when used server paging (tags IO, Cfg, Filters)

b)       specific page when used server paging (tags IO, Cfg, Filters, Body)

c)       row’s children when used server child paging (tags IO, Cfg, Filters, Body)

d)       server export to Excel (Export_Type=’1’) (tags IO, Cfg, Filters, LeftCols, Cols, RightCols)

 

<Grid> (Root tag, can accept any count of introduced child tags in any order)

 

   <IO ... attributes with request settings... />

 

   <Cfg ... attributes with grid settings read from cfg ... />

 

   <Filters> (list of filters read from cfg)

      <I ... row attributes ... ... cell attributes and values in Internal format ... >

          <U Ncolumn name’ ... cell attributes and value in DTD format ... />

          ... more tags <U> for other cells, in DTD format ...

      </I>

   </Filters>

 

   <LeftCols> (used in server export request)

      <C Name='column name' Width=’...’ Visible=’0/1’ />

      ... more tags <C> for other columns ...

   </LeftCols>

 

   <Cols> (used in server export request)

      <C Name='column name' Width=’...’ Visible=’0/1’ />

      ... more tags <C> for other columns ...

   </Cols>

 

   <RightCols> (used in server export request)

      <C Name='column name' Width=’...’ Visible=’0/1’ />

      ... more tags <C> for other columns ...

   </RightCols>  

 

   <Body> (List of all requested  pages or rows)

      <B ... attributes identifying page (by Pos) or row (by id) ... />

      ... More tags <B> ...

   </Body>

 

</Grid>

 

Communication with the server

 

1) Download of structure

On start TreeGrid downloads data from data source Text, Defaults and Layout. Does not send any request, just downloads data.

When server returns HTTP error or IO.Result < 0 the TreeGrid stops loading and shows fatal error.

 

2) Download of data

Next TreeGrid downloads data from data source Data. If Paging is not set to 3 (Server), does not send any request, just downloads all data.

When server returns HTTP error or IO.Result < 0 the TreeGrid stops loading and shows fatal error.

 

2a) Paging

If Paging is set to 3 (Server) it loads configuration from cookies and inserts it to the request (See XML request) and sends it to server and downloads prepared pages without data. This request contain filter and sorting settings.

Server prepares pages – calculates, sorts and filters rows and distributes rows to pages. And sets page names and results of aggregate functions for page and column.

Returned <Body> tag contains only <B> tags with attributes but without any child <I> tags.

 

When any not loaded page is displayed, TreeGrid downloads data for this page by sending appropriate request. The request for page (<B> tag) contains Rows attribute of page (if was set) or id attribute (if was set) and (always) Pos attribute as page index (position from 0).

The request also contains filter and sorting settings, the same as when pages body was downloaded.

 

When user changes sorting or filtering, TreeGrid reloads all data from data source Data with new configuration in request. And repeats loading of pages.

Re-calculations after cell change are still done on client. Calculated cells are not sent to server. Therefore server must also recalculate appropriate cells if changed values are saved to server.

 

The data of returned page can contain also defaults (<D> tags). These defaults are added to grid layout, but should be used only for data in the page they were loaded with.

 

Example of request for body (grid has columns named A,B,C,D,E):

<Grid>

<Cfg SortCols=’C,A’ SortTypes=’0,1’/>

<Filters><I id=’MyFilter’ C=’10’ CFilter=’1’ E=’A’ AFilter=’10’/></Filters>

</Grid>

 

Example of resulted body (grid has also one foot row: <I AFormula=’sum()’ CFormula=’sum(“D”)/2+A’/>)

<Grid>

<Body>

<B Count=’20’ Asum=’123’ Dsum=’312’ />

<B Count=’20’ Asum=’453’ Dsum=’6.5’ />

<B Count=’20’ Asum=’1297’ Dsum=’-142.76’ />

<B Count=’12’ Asum=’145’ Dsum=’349.7’ />

</Body>

</Grid>

 

Example of request for second page (grid has columns named A,B,C,D,E):

<Grid>

<Cfg SortCols=’C,A’ SortTypes=’0,1’/>

<Filters><I id=’MyFilter’ C=’10’ CFilter=’1’ E=’A’ AFilter=’10’/></Filters>

<Body><B Pos=’1’/></Body>

</Grid>

 

Example of resulted second page

<Grid>

<Body>

<B Pos=’1’>

<I id=’xa’ A=’10’ B=’20’ C=’10.3’ D=’-4.5’ E=’one’/>

... 18 rows ...

<I id=’xu’ A=’3’ B=’12’ C=’4.6’ D=’-3.5’ E=’twenty’/>

 </B>

</Body>

</Grid>

 

2b) Child paging

If ChildPaging is set to 3 (Server) it loads the server not send content of collapsed rows when downloading data or page.

When user expands collapsed not yet loaded row, TreeGrid sends the same request as for downloading page. The requested row is set as <B> tag with row’s attribute id. (For example: <Grid>...<Body><B id=’r123’/></Body></Grid>). And server returns the <B> tag with the same id and with content of the row’s children. Server must return all immediate children and children of all expanded rows.

ChildPaging can be set to 3 independently of Paging value.

 

The parent row must have set the Count attribute to at least 1. It is better if Count is set to real count of immediate children the row contains. And Expanded must be set “0”, because only not expanded rows can be downloaded asynchronously.

 

Example of request for children of row ‘xy’ (grid has columns named A,B,C,D,E):

<Grid>

<Cfg SortCols=’C,A’ SortTypes=’0,1’/>

<Filters><I id=’MyFilter’ C=’10’ CFilter=’1’ E=’A’ AFilter=’10’/></Filters>

<Body><B id=’xy’/></Body>

</Grid>

 

3) Upload of changed data

When automatic updates are set and user changes any data in the grid or when user clicks Save button on control panel, changed data are sent to the server. See XML upload.

The server can modify any row(s) and send changes back to grid in the same format.

The uploaded rows can have set these attributes:

                id – this attribute is always set to identify uploaded row. There are many ways to set this attribute, see Row’s identification tutorial.

                Deleted – The row have been deleted by user. No other attribute is set.

                Changed – Any cell’s value of the row have been changed. The row contain values of all changed cell. The row can also contain the Moved attribute.

                Moved – The row has been moved to new position. The Parent and Next attributes specify new position. The row can also contain Changed attribute.

                Added – The row is new row. The row contain new generated id. The Parent and Next attributes specify new position. The Def attribute specifies default values.

                               The row also contain all cell values, that are not the same as default values and are not calculated.

Parent attribute (Added, Moved) can be string for row id or number for page position, Next is string for row id.

When server returns HTTP error or IO.Result < 0, the TreeGrid shows message if provided and does not accept changes. The changes can be send again.

If server return HTTP OK and IO.Result is not set or is >= 0, the TreeGrid accepts all changes – deleted rows are physically deleted and other flags are cleared.

 

Example of changed data sent to server:

<Grid>

<Changes>

<I id=’xy’ Changed=’1’ A=’12’/>

<I id=’xa’ Moved=’1’ Parent=’aa’ Next=’xc’/>

<I id=’xz’ Added=’1’ Parent=’1’ Next=’’ A=’3’ B=’7’ C=’5.4’ D=’-3’ E=’twenty six’/>

<I id=’xg’ Deleted=’1’/>

</Changes>

</Grid>

 

 

 

 

 

 

 

 

 

 

Updates

 

3.2

Added Defaults description

 

3.6

Excluded from file TreeGridDataFormats.htm

 

3.8

Updated Extra short format

Added Very large tables section

 

4.2

Added section Identifying uploaded rows

 

4.3

Update XML structure - request