The code in XSBuiltIns does parse the millisecond part, but this part is never used in coding functions.
function TXSBaseTime.GetAsTime: TDateTime; begin Result := EncodeTime(Hour, Minute, Second, 0); end;
and
function TXSBaseCustomDateTime.GetAsDateTime: TDateTime; var BiasDT: TDateTime; BiasTime, BiasLocal: Integer; BiasHour, BiasMins: Word; begin { NOTE: In XML Years can exceed 9999 - that not the case for TDateTime. So here, there would be a problem with the conversion } Result := EncodeDateTime(Year, Month, Day, Hour, Minute, Second, 0);
and
function TXSBaseCustomDateTime.GetAsUTCDateTime: TDateTime; var AdjustDT: TDateTime; begin Result := EncodeDateTime(Year, Month, Day, Hour, Minute, Second, 0);
Since the latter is called from XMLTimeToDateTime, it is clear that the millisecond part is always 0.
All parsing and data storage is performed in internal classes (implementation parts), which cannot be accessed directly, except for through (broken) wrappers. IOW, you must write your own date / time analyzer.
In addition to all the ugliness found in XSBuiltIns, XMLTimeToDateTime actually parses the date twice. First, TXSDateTime.XSToNative is called, which parses the date / time, returns the result and saves only the original string, and then TXSCustomDateTime.GetAsUTCDateTime parses that string again. Euch!