FXCM makes available a feed for select instruments which are not updated in real time, though are refreshed on an interval. This feed is available in three 'flavors'. The xml returned is a valid XML documents with a Rates tag as the root with a Rate tag as child elements.

http://http://rates.fxcm.com/RatesXML
Code:
<Rate Symbol="EURUSD">
    <Bid>1.38694</Bid>
    <Ask>1.3872</Ask>
    <High>1.41729</High>
    <Low>1.38683</Low>
    <Direction>1</Direction>
    <Last>15:22:43</Last>
</Rate>
http://http://rates.fxcm.com/RatesXML2
Code:
<Rate Symbol="EURUSD">
    <Symbol>EURUSD</Symbol>
    <Bid>1.3849</Bid>
    <Ask>1.38509</Ask>
    <High>1.41729</High>
    <Low>1.38485</Low>
    <Direction>0</Direction>
    <Last>15:30:13</Last>
</Rate>
http://http://rates.fxcm.com/RatesXML3
Code:
<Rate Symbol="EURUSD">
    <Symbol>EURUSD</Symbol>
    <Bid>1.38446</Bid>
    <Ask>1.38472</Ask>
    <High>1.41729</High>
    <Low>1.38426</Low>
    <Direction>-1</Direction>
    <Last>15:30:43</Last>
    <Date>2011-10-31</Date>
</Rate>
With any of the three formats above, it is possible to create a web page that will access the feed at a regular interval and display the rate information using AJAX methodology. An example of code used, not compatible with Internet Explorer, to do this.

rates.js
PHP Code:
// declare global variables used in the gadget
var loadingurlrssXML;
// a 'constant' structure for the outputting of each instrument's data
// each class is defined in FXCMRates.css
// the background of the current rates section will change color depending on the direction
var strWrapper =
  
"<div class='instrument'>" +              // create an instrument section
    
"<div class='identity'>" +              // create an identity section
      
"<div class='last'>[last]</div>" +    // create a section for the time of last update
      
"<div class='symbol'>[symbol]</div>" +// create a section to display the symbol
      
"<div class='date'>[date]</div>" +    // create a section for the date of last update
    
"</div>" +                              // close the identity section
    
"<div class='rates'>" +                 // create a rates section
      
"<div class='high'>[high]</div>" +    // create a section to display the high of the instrument
      
"<div class='current [direction]'>" // create a current rate section
        
"<div class='bid'>[bid]</div>" +    // create a section to display the bid rate
        
"<div class='ask'>[ask]</div>" +    // create a section to display the ask rate
      
"</div>" +                            // close the current rate section
      
"<div class='low'>[low]</div>" +      // create a section to display the low of the instrument
    
"</div>" +                              // close the rates section
    
"<div class='clear'></div>" +           // create a section to ensure page alignment
  
"</div>";                                 // close the instrument section

/**
 * init()
 * triggered at the Load event for the 'page'
 */
function init()
{
  
// define the a reference to a section of the page
  
loading document.getElementById("loading");
  
// define the url to feed to process
  
url "http://rates.fxcm.com/RatesXML3";
  
// prime the page by calling getRSS()
  
getRSS();
  
// set a regular interval to call getRSS() evern 60 seconds
  
setInterval("getRSS()"60 1000);
}

/**
 * getRSS()
 * Creates an ActiveX instance of the XMLHttpRequest object to request a remote web document to be
 * accessed through a DOM.
 */
function getRSS()
{
  
// display a note within the loading section of the page that a connection is being attempted
  
loading.innerText "Connecting...";           
  
// define a new XMLHttpRequest object
  
rssObj = new XMLHttpRequest();
  
// define a connection to the specified url, denoting it is an asynchronous call
  
rssObj.open("GET"urltrue);
  
// when state of the connection changes, perform these actions
  
rssObj.onreadystatechange = function()
  {
    
// if the state is Completed (4)
    
if (rssObj.readyState == 4)
    {
      
// if the status of the request is Ok (200)
      
if (rssObj.status == 200)
      {
        
// create a new timestamp
        
now = new Date();
        
// define reference to the minutes
        
min now.getMinutes();
        
// define reference to the seconds
        
sec now.getSeconds();
        
// display a formated timestamp of the refresh
        
loading.innerHTML "Last updated:<br />" +
          (
now.getMonth() + 1) + "/" + (now.getDate()) + "/" + (now.getFullYear()) + " " +
          
now.getHours() + ":" + ((min 10) ? "0" min min) + ":" + ((sec 10) ? "0" sec sec);
        
// save the response DOM as the global rssXML
        
rssXML rssObj.respon---ML;
        
// call the function to display the new rates
        
parseRSS();
        
// if there was an error, clear the interval timer
        
if (chkConnclearInterval(chkConn);
      }
      
// othwise there may be a problem
      
else
      {
        
// define a reference to a connection check
        
var chkConn;
        
// denote that the attempt failed
        
loading.innerText "Unable to connect";
        
// set an interval to try again in 30 seconds
        
chkConn setInterval("getRSS()"30 1000);
      }
    }
    
// otherwise 
    
else
      
// denote that the data is a being loaded
      
loading.innerText "Loading...";
  }
  
// send the request and initiate the connection
  
rssObj.send();
}

/**
 * parseRSS()
 * having recieved the external page as a DOM, traverse it to format the data to this page
 */
function parseRSS()
{
  
// check the preferences to see whether there should be a filter on the instruments
  
instrFilter ""// declare and prime the instrument filter
  // read into the instrument filter the value of the associated preference
  
instrFilter System.Gadget.Settings.readString("instrFilter");
  
// if the instrument filter is undefined in preferences, set the filter to all
  
if (instrFilter == ""instrFilter "*";
  
// create a reference to the html wrapper for the instrument display
  
targetDiv document.getElementById("instruments");
  
// create a collection of all the Rate elements in the feed
  
rates rssXML.getElementsByTagName("Rate");
  
// clear the html wrapper of content
  
targetDiv.innerHTML "";
  
// iterate through the Rate elements
  
for(0rates.lengthi++)
  {
    
// define which symbol currently being processed
    
symbol rssXML.getElementsByTagName("Symbol")[i].childNodes[0].nodeValue;
    
// check to see if the symbol passes the current filter
    
if(instrFilter.indexOf("*") >= || instrFilter.toUpperCase().indexOf(symbol) >= 0)
      
/**
       * use javascript String.replace function and chaining to populate values into the html
       * structure defined in strWrapper, appending the result to the html wrapper
       *
       * this occurs by referencing the appropriate tag of the same index
       */
      
targetDiv.innerHTML += strWrapper
        
.replace("[direction]""d" rssXML.getElementsByTagName("Direction")[i].childNodes[0].nodeValue)
        .
replace("[last]"rssXML.getElementsByTagName("Last")[i].childNodes[0].nodeValue)
        .
replace("[symbol]"symbol)
        .
replace("[date]"rssXML.getElementsByTagName("Date")[i].childNodes[0].nodeValue)
        .
replace("[high]"fxRate(rssXML.getElementsByTagName("High")[i].childNodes[0].nodeValuesymbol))
        .
replace("[bid]"fxRate(rssXML.getElementsByTagName("Bid")[i].childNodes[0].nodeValuesymbol))
        .
replace("[ask]"fxRate(rssXML.getElementsByTagName("Ask")[i].childNodes[0].nodeValuesymbol))
        .
replace("[low]"fxRate(rssXML.getElementsByTagName("Low")[i].childNodes[0].nodeValuesymbol))
      ;
  }
  
// add an adjustment section to keep page alignment, class defined in FXCMRates.css
  
targetDiv.innerHTML += "<div class='clear'></div>";
}

/**
 * fxRate(double, string)
 * format a given rate with trailing zeros depending on the instrument symbol
 */
function fxRate(ratesymbol)
{
  
// ensure that the double value is a numerical value
  
parseFloat(rate);
  
// declare and prime the return value as a string
  
str "";
  
// if the instrument uses the Japanese Yen, set to 3 decimal places
  
if(symbol.indexOf("JPY") > 0str += r.toFixed(3);
  
// if the instrument uses Silver or Gold, set to 2 decimal places
  
else if((symbol.indexOf("XAU") >= 0) || (symbol.indexOf("XAG") >= 0)) str += r.toFixed(2);
  
// if the instrument is the USDOLLAR, set to 0 decimal places
  
else if((symbol.indexOf("DOLLAR") >= 0)) str += r.toFixed(0);
  
// otherwise, set to 5 decimal places
  
else str += r.toFixed(5);
  
// return an html formated string, classes defined in FXCMRates.css
  
return "<span class='reduce'>" str.slice(0, -2) + "</span>" str.slice(-2str.length);

rates.htm
HTML Code:
<!DOCTYPE html>
<html>
  <head>
    <script type="text/jscript" language="jscript" src="rates.js"></script>
    <style>
#gadgetContent
{
  margin: 8px;
  padding: 0;
  position: relative;
  text-align: center;
  overflow: hidden;
}
/* #loading { color: #fff;  } */
#loading, #instruments { width: 242px; height: 36px; }
#instruments, .instrument, .identity, .rates, .current { position: relative; }
.identity, .rates  { width: 50%;}
.last, .high, .low, .date, .current, .symbol { height: 16px; font-size: 13px; width: 100%; }
.bid, .ask { font-size: 12px; text-align: right; width: 49%; margin-right: 1%; }
.bid .reduce, .ask .reduce { font-size: 9px; }
.symbol, .current { height: 32px; font-size: 20px; }
.identity, .rates, .bid, .ask { float:left; }
.current, .symbol { line-height: 32px; }
.d1  { background-color: #00A; color: #fff; }
.d0  { background-color: #888; color: #fff; }
.d-1 { background-color: #A00; color: #fff; }
.instruments, .instrument, .identity, .rates, .current, .last, .high, .low, .date, .symbol
{ display: block; margin: 0; padding: 0; text-align: center; }
.instrument
{
  float: left;
  width: 220px;
  height: 64px;
  border-style: inset;
  border-width: 2px;
  margin: 0;
}
.last, .high, .low, .date, .current, .symbol, .bid, .ask, #loading
{
  color: #fff;
  text-shadow: 1px 1px 1px #000;
}
#instruments
{
  height: 323px;
  overflow-y: auto;
  margin: 0;
}
.clear { clear: both; }
    </style>
  </head>
  <body onload="init();">
    <div id="gadgetContent">
      <div id="loading">loading...</div>
      <div id="instruments"></div>
    </div>
  </body>
</html>
Please note that the core of the script is the use of the XMLHttpRequest object which connects and creates an XML DOM for the given URL, in this case http://http://rates.fxcm.com/RatesXML3. As such, for many browsers, it will not run on your local computer due to security.

Alternatively, with a few adjustments, you can create your own Adobe Air or Windows 7 Gadget based on the code above.