Hi,

Just to give my point of view from my personnal experience, I totally agree with Krzysztof on this. A document versioning information is necessary when previous data has been saved in a wrong way, and on the upgrading point, this is also entirely true. The update procedure must be independant of the core code as it should be incremental and some "old" upgrades could be not always supported by the main structure.

Following is an example of what I'm applying in my software:

const
  SOFTWARE_VERSION = 4.3;

procedure Upgrade;
var
  CurrentVersion
begin
  CurrentVersion := GetCurrentVersionFromXmlFile;
  
  if CurrentVersion > SOFTWARE_VERSION then
  begin
    //Warn user that it's software version seems too old to correctly open the file
    return;
  end;
  
  if CurrentVersion <= 1.0 then
  begin
    //APPLY ?.? -> 1.0 Upgrades here
    CurrentVersion := 1.0;
  end;
  
  if CurrentVersion <= 2.0 then
  begin
    //APPLY 1.0 -> 2.0 Upgrades here
    CurrentVersion := 2.0;
  end;
  
  if CurrentVersion <= 3.0 then
  begin
    //APPLY 2.0 -> 3.0 Upgrades here
    CurrentVersion := 3.0;
  end;
  
  // etc...
  if CurrentVersion <= xx.yy then
  begin
    //APPLY 3.0 -> xx.yy Upgrades here
    CurrentVersion := xx.yy ;
  end;
  
  if CurrentVersion <= SOFTWARE_VERSION then
  begin
    //APPLY xx.yy -> SOFTWARE_VERSION Upgrades here
    CurrentVersion := SOFTWARE_VERSION;
    
    //Warn user that it's file project has been updated (to a compliant application format) and changes will be kept after a save
  end;
  
end;

Note that when I'm applying the version_A -> version_B upgrade, I'm not relying on the core code, all is managed internally by the upgrade procedure in order to avoid upgrade fails that could occured due to a progressive refactoring (deletion, renaming, etc.)