Listing 1: HTML used to call FusionCharts
<META Http-Equiv=”Pragma” Content=”no-cache”>
<head>
<script language=”JavaScript” src=”FusionCharts/FusionCharts.js”</script>
</head>
<body bgcolor=”#FFFFFF” onbeforeunload=”opertion.location.reload();”>
<div id=”chartdiv” align=”center”>loading chart, please wait.</div>
<script type=”text/javascript”>
var myChart = new FusionCharts(“FusionCharts/FCF_Funnel.swf”, “Funnel”, “500”, “400”);
myChart.setDataURL(“data.XML”);
myChart.render(“chartdiv”);
</script>
</body>
</html>
Listing 2: XML data for FusionCharts
<graph caption=”Net Revenue” shownames=”1” showValues=”1” showLimits=”1” rotateNames=”1” animation=”1” showLegend=”1” showPercentageInLabel=”1” showColumnShadow=”1” showBarShadow=”1” formatNumber=”1” formatNumberScale=”0” decimalSeparator=”.” thousandSeparator=”,” decimalPrecision=”2” divLineDecimalPrecision=”2” limitsDecimalPrecision=”2” showhovercap=”1” >
<set name=”January” value= “17400.00” isSliced= “1” />
<set name=”February” value= “19800.00” />
<set name=”March” value= “21800.00” />
<set name=”April” value= “23800.00” />
<set name=”May” value= “29600.00” />
<set name=”June” value= “27600.00” />
<set name=”July” value= “31800.00” />
<set name=”August” value= “39700.00” />
<set name=”September” value= “37800.00” />
<set name=”October” value= “21900.00” />
<set name=”November” value= “32900.00” />
<set name=”December” value= “39800.00” />
<trendlines>
</trendlines>
</graph>
Listing 3: of_preview method used to display chart
n_cst_fusioncharts lnv_fusioncharts
lnv_fusioncharts = tab_chart.tabpage_config.tab_chartoptions.of_get()
#IF DEFINED PBWEBFORM THEN
lnv_fusioncharts.of_apply(lnv_fusioncharts.of_generatehtml_javascript(),lnv_fusioncharts.htmlpagename)
lnv_fusioncharts.of_apply(lnv_fusioncharts.of_generatedataxml( ),lnv_fusioncharts.dataxmlname)
tab_chart.tabpage_preview.shl_chart.Embedded = true
string ls_url
ls_url = lnv_fusioncharts.of_geturl(lnv_fusioncharts.htmlpagename)
tab_chart.tabpage_preview.shl_chart.url = ls_url
#END IF
Listing 4: of_generatehtml_javascript function
string html_content
//set default value once the initial value is empty
iif(chart_width=’’ and isnumber(chart_width),500,chart_width)
iif(chart_bgcolor=’’,’FFFFFF’,chart_bgcolor)
iif(chart_height=’’ and isnumber(chart_height),500,chart_height)
iif(chartid=’’,’Column3D’,chartid)
iif(chartswf=’’,’FCF_MSColumn3D.swf’,chartswf)
iif(dataxmlname=’’,’data.XML’,dataxmlname)
html_content = char(13) + char(10) + ‘<html>’
html_content = char(13) + char(10) + ‘<META Http-Equiv=”Pragma” Content=”no-cache”>’
html_content += char(13) + char(10) + space(2)+ ‘<head>’
html_content += char(13) + char(10) + space(2)+ ‘<script language=”JavaScript” src=”FusionCharts/FusionCharts.js”</script>’
html_content += char(13) + char(10) + space(2)+ ‘</head>’
html_content += char(13) + char(10) + space(4) + ‘<body bgcolor=”#’+ chart_bgcolor + ‘” onbeforeunload=”opertion.location.reload();”>’
html_content += char(13) + char(10) + space(6)+ ‘<div id=”chartdiv” align=”center”>loading chart, please wait.</div>’
html_content += char(13) + char(10) + space(6) + ‘<script type=”text/javascript”>’
html_content += char(13) + char(10) + space(8) + ‘ var myChart = new FusionCharts(“FusionCharts/’ + chartswf + ‘”, “’+chartid+’”, “’ + chart_width + ‘”, “’ + chart_height + ‘”);’
html_content += char(13) + char(10) + space(8) + ‘myChart.setDataURL(“’ + dataxmlname + ‘”);’
html_content += char(13) + char(10) + space(8) + ‘myChart.render(“chartdiv”);’
html_content += char(13) + char(10) + space(6) + ‘</script>’
html_content += char(13) + char(10) + space(2) +’</body>’
html_content += char(13) + char(10) + “</html>”
return html_content
Listing 5: of_generatedataxml
string ls_dataxml
string ls_graphAttr,ls_content
//<graph> Attributes
ls_graphAttr =’<graph ‘
//Chart and Axis Titles
ls_graphAttr += iif( caption =’’,’’, ‘caption=”’+ caption +’” ‘)
ls_graphAttr += iif( subcaption =’’,’’,’subCaption=”’+ subcaption +’” ‘)
ls_graphAttr += iif( xaxisname =’’,’’,’xAxisName=”’+ xaxisname +’” ‘)
ls_graphAttr += iif( yaxisname =’’,’’,’yAxisName=”’+ yaxisname +’” ‘)
//Background Properties
ls_graphAttr += iif( bgcolor =’’,’’, ‘bgColor=”’+ bgcolor +’” ‘)
ls_graphAttr += iif( bgalpha =’’,’’, ‘bgAlpha=”’+ bgalpha +’” ‘)
ls_graphAttr += iif( bgswf =’’,’’, ‘bgSWF=”’+ bgswf +’” ‘)
//Canvas Properties
ls_graphAttr += iif( canvasbgcolor =’’,’’, ‘canvasBgColor=”’+ canvasbgcolor +’” ‘)
ls_graphAttr += iif( canvasbgalpha =’’,’’, ‘canvasBgAlpha=”’+ canvasbgalpha +’” ‘)
ls_graphAttr += iif( canvasbordercolor =’’,’’, ‘canvasBorderColor=”’+ canvasbordercolor +’” ‘)
ls_graphAttr += iif( canvasborderthickness =’’,’’, ‘canvasBorderThickness=”’+ canvasborderthickness +’” ‘)
ls_graphAttr += iif( canvasbasecolor =’’,’’, ‘canvasBaseColor=”’+ canvasbasecolor +’” ‘)
ls_graphAttr += iif( canvasbasedepth =’’,’’, ‘canvasBaseDepth=”’+ canvasbasedepth +’” ‘)
ls_graphAttr += iif( canvasbgdepth =’’,’’, ‘canvasBgDepth=”’+ canvasbgdepth +’” ‘)
ls_graphAttr += iif( showcanvasbg=’’,’’, ‘showCanvasBg=”’+showcanvasbg+’” ‘)
ls_graphAttr += iif( showcanvasbase=’’,’’, ‘showCanvasBase=”’+showCanvasBase+’” ‘)
//Chart Numerical Limits
choose case chartid
case ‘Pie2D’,’Pie3D’
// no Chart Numerical Limits
case else
ls_graphAttr += iif( yaxisminvalue =’’,’’, ‘yAxisMinValue=”’+ yaxisminvalue +’” ‘)
ls_graphAttr += iif( yaxismaxvalue =’’,’’, ‘yAxisMaxValue=”’+ yaxismaxvalue +’” ‘)
end choose
//Generic Properties
ls_graphAttr += iif( shownames=’’,’’, ‘shownames=”’+shownames+’” ‘)
ls_graphAttr += iif( showvalues=’’,’’, ‘showValues=”’+showvalues+’” ‘)
ls_graphAttr += iif( showlimits=’’,’’, ‘showLimits=”’+showlimits+’” ‘)
ls_graphAttr += iif( rotatenames=’’,’’, ‘rotateNames=”’+rotatenames+’” ‘)
ls_graphAttr += iif( animation=’’,’’, ‘animation=”’+animation+’” ‘)
ls_graphAttr += iif( showlegend=’’,’’, ‘showLegend=”’+showlegend+’” ‘)
ls_graphAttr += iif( showpercentagevalues=’’,’’, ‘showPercentageValues=”’+showpercentagevalues+’” ‘)
ls_graphAttr += iif( showpercentageinlabel=’’,’’, ‘showPercentageInLabel=”’+showpercentageinlabel+’” ‘)
ls_graphAttr += iif( showcolumnshadow=’’,’’, ‘showColumnShadow=”’+showcolumnshadow+’” ‘)
ls_graphAttr += iif( showbarshadow=’’,’’, ‘showBarShadow=”’+showbarshadow+’” ‘)
choose case chartid
case ‘MSLine’
//Line Properties
ls_graphAttr += iif( linecolor =’’,’’, ‘lineColor=”’+ linecolor +’” ‘)
ls_graphAttr += iif( linethickness =’’,’’, ‘lineThickness=”’+ linethickness +’” ‘)
ls_graphAttr += iif( linealpha =’’,’’, ‘lineAlpha=”’+ linealpha +’” ‘)
//Line Shadow Properties
ls_graphAttr += iif( showshadow=’’,’’, ‘showShadow=”’+showshadow+’” ‘)
ls_graphAttr += iif( shadowcolor =’’,’’, ‘shadowColor=”’+ shadowcolor +’” ‘)
ls_graphAttr += iif( shadowthickness =’’,’’, ‘shadowThickness=”’+ shadowthickness +’” ‘)
ls_graphAttr += iif( shadowalpha =’’,’’, ‘shadowAlpha=”’+ shadowalpha +’” ‘)
ls_graphAttr += iif( shadowxshift =’’,’’, ‘shadowXShift=”’+ shadowxshift +’” ‘)
ls_graphAttr += iif( shadowyshift =’’,’’, ‘shadowYShift=”’+ shadowyshift +’” ‘)
//Line Anchor properties
ls_graphAttr += iif( showanchors=’’,’’, ‘showAnchors=”’+showanchors+’” ‘)
ls_graphAttr += iif( anchorsides =’’,’’, ‘anchorSides=”’+ anchorsides +’” ‘)
ls_graphAttr += iif( anchorradius =’’,’’, ‘anchorRadius=”’+ anchorradius +’” ‘)
ls_graphAttr += iif( linecolor =’’,’’, ‘anchorBorderColor=”’+ linecolor +’” ‘)
ls_graphAttr += iif( anchorBorderThickness =’’,’’, ‘anchorBorderThickness=”’+ anchorBorderThickness +’” ‘)
ls_graphAttr += iif( anchorbgcolor =’’,’’, ‘anchorBgColor=”’+ anchorbgcolor +’” ‘)
ls_graphAttr += iif( anchorbgalpha =’’,’’, ‘anchorBgAlpha=”’+ anchorbgalpha +’” ‘)
ls_graphAttr += iif( anchoralpha =’’,’’, ‘anchorAlpha=”’+ anchoralpha +’” ‘)
case ‘Pie2D’,’Pie3D’
//Pie Properties
ls_graphAttr += iif( pieradius =’’,’’, ‘pieRadius=”’+ pieradius +’” ‘)
ls_graphAttr += iif( pieslicedepth =’’,’’, ‘pieSliceDepth=”’+ pieslicedepth +’” ‘)
ls_graphAttr += iif( pieyscale =’’,’’, ‘pieYScale=”’+ pieyscale +’” ‘)
ls_graphAttr += iif( pieborderthickness =’’,’’, ‘pieBorderThickness=”’+ pieborderthickness +’” ‘)
ls_graphAttr += iif( pieborderalpha =’’,’’, ‘pieBorderAlpha=”’+ pieborderalpha +’” ‘)
ls_graphAttr += iif( piefillalpha =’’,’’, ‘pieFillAlpha=”’+ piefillalpha +’” ‘)
// Pie 2D Name/Value display distance control
ls_graphAttr += iif( slicingdistance =’’,’’, ‘slicingDistance=”’+ slicingdistance +’” ‘)
ls_graphAttr += iif( nametbdistance =’’,’’, ‘nameTBDistance=”’+ nametbdistance +’” ‘)
//Pie 2D Shadow Properties
ls_graphAttr += iif( pieshowShadow =’’,’’, ‘showShadow=”’+ pieshowShadow +’” ‘)
ls_graphAttr += iif( pieshadowcolor =’’,’’, ‘shadowColor=”’+ pieshadowcolor +’” ‘)
ls_graphAttr += iif( pieshadowalpha =’’,’’, ‘shadowAlpha=”’+ pieshadowalpha +’” ‘)
ls_graphAttr += iif( pieshadowxshift =’’,’’, ‘shadowXShift=”’+ pieshadowxshift +’” ‘)
ls_graphAttr += iif( pieshadowyshift =’’,’’, ‘shadowYShift=”’+ pieshadowyshift +’” ‘)
end choose
//Font Properties
ls_graphAttr += iif( basefont =’’,’’, ‘baseFont=”’+ basefont +’” ‘)
ls_graphAttr += iif( basefontsize =’’,’’, ‘baseFontSize=”’+ basefontsize +’” ‘)
ls_graphAttr += iif( baseFontColor =’’,’’, ‘baseFontColor=”’+ baseFontColor +’” ‘)
ls_graphAttr += iif( outCnvBaseFont =’’,’’, ‘outCnvBaseFont=”’+ outCnvBaseFont +’” ‘)
ls_graphAttr += iif( outcnvbasefontcolor =’’,’’, ‘outCnvBaseFontColor=”’+ outcnvbasefontcolor +’” ‘)
ls_graphAttr += iif( outCnvBaseFontSze =’’,’’, ‘outCnvBaseFontSze=”’+ outCnvBaseFontSze +’” ‘)
//Number Formatting Options
ls_graphAttr += iif( numberprefix =’’,’’, ‘numberPrefix=”’+ numberprefix +’” ‘)
ls_graphAttr += iif( numbersuffix =’’,’’, ‘numberSuffix=”’+ numbersuffix +’” ‘)
ls_graphAttr += iif( formatnumber=’’,’’, ‘formatNumber=”’+formatnumber+’” ‘)
ls_graphAttr += iif( formatnumberscale=’’,’’, ‘formatNumberScale=”’+formatnumberscale+’” ‘)
ls_graphAttr += iif( decimalseparator =’’,’’, ‘decimalSeparator=”’+ decimalseparator +’” ‘)
ls_graphAttr += iif( thousandseparator =’’,’’, ‘thousandSeparator=”’+ thousandseparator +’” ‘)
ls_graphAttr += iif( decimalprecision =’’,’’, ‘decimalPrecision=”’+ decimalprecision +’” ‘)
ls_graphAttr += iif( divlinedecimalprecision =’’,’’, ‘divLineDecimalPrecision=”’+ divlinedecimalprecision +’” ‘)
ls_graphAttr += iif( limitsdecimalprecision =’’,’’, ‘limitsDecimalPrecision=”’+ limitsdecimalprecision +’” ‘)
//Zero Plane
ls_graphAttr += iif( zeroplanethickness =’’,’’, ‘zeroPlaneThickness=”’+ zeroplanethickness +’” ‘)
ls_graphAttr += iif( zeroplanecolor =’’,’’, ‘zeroPlaneColor=”’+ zeroplanecolor +’” ‘)
ls_graphAttr += iif( zeroplanealpha =’’,’’, ‘zeroPlaneAlpha=”’+ zeroplanealpha +’” ‘)
// zerPlaneShowBorder and zeroPlaneBorderColor are only for Coloum 3D
ls_graphAttr += iif( zeroPlaneShowBorder=’’,’’, ‘zeroPlaneShowBorder=”’+zeroPlaneShowBorder+’” ‘)
ls_graphAttr += iif( zeroplanebordercolor =’’,’’, ‘zeroPlaneBorderColor=”’+ zeroplanebordercolor +’” ‘)
//Divisional Lines (Horizontal)
ls_graphAttr += iif( numdivlines =’’,’’, ‘numdivlines=”’+ numdivlines +’” ‘)
ls_graphAttr += iif( divlinecolor =’’,’’, ‘divlinecolor=”’+ divlinecolor +’” ‘)
ls_graphAttr += iif( divlinethickness =’’,’’, ‘divLineThickness=”’+ divlinethickness +’” ‘)
ls_graphAttr += iif( divlinealpha =’’,’’, ‘divLineAlpha=”’+ divlinealpha +’” ‘)
ls_graphAttr += iif( showDivLineValue=’’,’’, ‘showDivLineValue=”’+showDivLineValue+’” ‘)
ls_graphAttr += iif( showalternatehgridcolor=’’,’’, ‘showAlternateHGridColor=”’+showalternatehgridcolor+’” ‘)
ls_graphAttr += iif( alternateHGridColor =’’,’’, ‘showDivLineValue=”’+ alternateHGridColor +’” ‘)
ls_graphAttr += iif( alternatehgridalpha =’’,’’, ‘alternateHGridAlpha=”’+ alternatehgridalpha +’” ‘)
//Divisional Lines (Vertical)
ls_graphAttr += iif( numvdivlines =’’,’’, ‘numVDivLines=”’+ numvdivlines +’” ‘)
ls_graphAttr += iif( vdivlinecolor =’’,’’, ‘VDivlinecolor=”’+ vdivlinecolor +’” ‘)
ls_graphAttr += iif( vdivlinethickness =’’,’’, ‘VDivLineThickness=”’+ vdivlinethickness +’” ‘)
ls_graphAttr += iif( vdivlinealpha =’’,’’, ‘VDivLineAlpha=”’+ vdivlinealpha +’” ‘)
ls_graphAttr += iif( showalternatevgridcolor=’’,’’, ‘showAlternateVGridColor=”’+showalternatevgridcolor+’” ‘)
ls_graphAttr += iif( alternatevgridcolor =’’,’’, ‘alternateVGridColor=”’+ alternatevgridcolor +’” ‘)
ls_graphAttr += iif( alternatevgridalpha =’’,’’, ‘alternateVGridAlpha=”’+ alternatevgridalpha +’” ‘)
//Hover Caption Properties
ls_graphAttr += iif( showhovercap=’’,’’, ‘showhovercap=”’+showhovercap+’” ‘)
ls_graphAttr += iif( hovercapbgcolor =’’,’’, ‘hoverCapBgColor=”’+ hovercapbgcolor +’” ‘)
ls_graphAttr += iif( hovercapbordercolor =’’,’’, ‘hoverCapBorderColor=”’+ hovercapbordercolor +’” ‘)
ls_graphAttr += iif( hovercapsepchar =’’,’’, ‘hoverCapSepChar=”’+ hovercapsepchar +’” ‘)
//Chart Margins
ls_graphAttr += iif(chartleftmargin =’’,’’, ‘chartLeftMargin=”’+ chartleftmargin +’” ‘)
ls_graphAttr += iif( chartrightmargin =’’,’’, ‘chartRightMargin=”’+ chartrightmargin +’” ‘)
ls_graphAttr += iif( charttopmargin =’’,’’, ‘chartTopMargin=”’+ charttopmargin +’” ‘)
ls_graphAttr += iif( chartbottommargin =’’,’’, ‘chartBottomMargin=”’+ chartbottommargin +’” ‘)
ls_graphAttr += ‘ >’
int i,j,categorycount,seriescount,valuecount
string ls_data
string ls_category
categorycount = UpperBound(category)
Choose case chartid
case ‘Pie3D’,’Pie2D’,’Doughnut2D’,’Funnel’
// <set> element -- <value> element
//only display the data from series[1]
for i = 1 to categorycount
ls_data += char(13) + char(10) + ‘<set name=”’ +category[i].categoryname + ‘” ‘
ls_data +=iif(series[1].seriesvalue[i].value=’’,’’, ‘value= “’ + series[1].seriesvalue[i].value +’” ‘)
ls_data +=iif(series[1].seriesvalue[i].valuecolor=’’,’’, ‘color= “’ + series[1].seriesvalue[i].valuecolor +’” ‘)
ls_data +=iif(series[1].seriesvalue[i].valuehoverText=’’,’’, ‘hoverText= “’ + series[1].seriesvalue[i].valuehoverText +’” ‘)
ls_data +=iif(series[1].seriesvalue[i].valuealpha=’’,’’, ‘alpha= “’ + series[1].seriesvalue[i].valuealpha +’” ‘)
ls_data +=iif(series[1].seriesvalue[i].valueisSliced=’’,’’, ‘isSliced= “’ + series[1].seriesvalue[i].valueisSliced +’” ‘)
ls_data+=’ />’
next
case else
//<categories> element
ls_category = char(13) + char(10) +’<categories ‘
ls_category +=iif(categoriesfont=’’,’’,’font=”’+categoriesfont+’” ‘)
ls_category +=iif(categoriesfontsize=’’,’’,’fontsize=”’+categoriesfontsize+’” ‘)
ls_category +=iif(categoriesfontcolor=’’,’’,’fontcolor=”’+categoriesfontcolor+’” ‘)
ls_category +=’ >’
// <category> element
for i = 1 to categorycount
ls_category += char(13) + char(10) + ‘<category name=”’ + category[i].categoryname +’” ‘
ls_category +=iif(category[i].categoryhoverText=’’,’’, ‘hoverText= “’ + category[i].categoryhoverText +’” ‘)
ls_category +=iif(category[i].categoryshowName=’’,’’, ‘showName= “’ + category[i].categoryshowName +’” ‘)
ls_category +=’ />’
next
ls_category += char(13) + char(10) + ‘ </categories>’
//<dataset> element -- <series> element
// <set> element -- <value> element
seriescount = UpperBound(series)
if seriescount = 0 then of_addseries(‘’)
valuecount = UpperBound(series[1].seriesvalue)
for i = 1 to seriescount
ls_data += char(13) + char(10) + ‘<dataset ‘
ls_data += iif(seriescount= 0, ‘’,’ seriesname=”’ +series[i].seriesname + ‘” ‘)
ls_data +=iif(series[i].seriescolor=’’,’’, ‘color= “’ + series[i].seriescolor +’” ‘)
ls_data +=iif( series[i].seriesalpha=’’,’’, ‘alpha= “’ + series[i].seriesalpha +’” ‘)
ls_data +=iif( series[i].seriesshowValues=’’,’’, ‘showValues= “’ + series[i].seriesshowValues +’” ‘)
ls_data+=’ >’
for j = 1 to valuecount
if series[i].seriesvalue[j].value=’’ or isnull(series[i].seriesvalue[j].value) then
ls_data += char(13) + char(10) + space(2) + ‘< set />’
else
ls_data +=char(13) + char(10) + space(2)+ ‘<set value = “’ +series[i].seriesvalue[j].value+’” ‘
ls_data +=iif(series[i].seriesvalue[j].valuecolor=’’,’’, ‘color= “’ + series[i].seriesvalue[j].valuecolor +’” ‘)
ls_data +=iif(series[i].seriesvalue[j].valuelink=’’,’’, ‘link= “’ + series[i].seriesvalue[j].valuelink +’” ‘)
ls_data +=iif(series[i].seriesvalue[j].valuealpha=’’,’’, ‘alpha= “’ + series[i].seriesvalue[j].valuealpha +’” ‘)
ls_data+= ‘ />’
end if
next
ls_data+=char(13) + char(10) +’ </dataset>’
next
end choose
//<trendLines>
string ls_trendLinesAttr
ls_trendLinesAttr = ‘<trendlines>’
int trendlinecount
trendlinecount = upperbound(trendlines)
if trendlinecount> 0 then
for i =1 to trendlinecount
ls_trendLinesAttr += char(13) + char(10) + ‘<line ‘
ls_trendLinesAttr += iif( trendlines[i].startvalue =’’,’’, ‘startValue=”’+ trendlines[i].startvalue +’” ‘)
ls_trendLinesAttr += iif( trendlines[i].endvalue =’’,’’, ‘endValue=”’+ trendlines[i].endvalue +’” ‘)
ls_trendLinesAttr += iif( trendlines[i].color =’’,’’, ‘color=”’+ trendlines[i].color +’” ‘)
ls_trendLinesAttr += iif( trendlines[i].displayvalue =’’,’’, ‘displayValue=”’+ trendlines[i].displayvalue +’” ‘)
ls_trendLinesAttr += iif( trendlines[i].thickness =’’,’’, ‘thickness=”’+ trendlines[i].thickness +’” ‘)
ls_graphAttr += iif( trendlines[i].isTrendZone=’’,’’, ‘isTrendZone=”’+trendlines[i].isTrendZone+’” ‘)
ls_graphAttr += iif( trendlines[i].showOnTop=’’,’’, ‘showOnTop=”’+trendlines[i].showOnTop+’” ‘)
ls_trendLinesAttr += iif( trendlines[i].alpha =’’,’’, ‘alpha=”’+ trendlines[i].alpha +’” ‘)
ls_trendLinesAttr +=’ />’
next
end if
ls_trendLinesAttr += char(13) + char(10) + ‘</trendlines>’
ls_dataxml = char(13) + char(10) + ls_graphAttr + char(13) + char(10) + ls_category + ls_data + char(13) + char(10) + ls_trendLinesAttr + char(13) + char(10) + ‘</graph>’
return ls_dataxml