Tja, im Prinzip ist das aktuelle Verhalten "eigentlich" richtig.
* in der
XML wird platformunabhängig gespeichert (Englisch mit Dezimal
punkt)
* beim Auslesen wird aus dem Text ein Variant/OleVariant
* und Variant/OleVariant nimmt beim Umwandeln die aktuellen Systemeinstellungen
(nja, eigentlich falsch ... der sollte besser die Programmeinstellungen nehmen aber so lange du sie nicht änderst, passt es)
* und da das bei dir ein Dezimal
komma ist (Deutsch), wird der Punkt ignoriert
Double-from-
XML: TXMLNode.GetNodeValue -> GetText -> _VarToReal -> _VarToDouble -> varOleStr:VarToDoubleAsString - VarR8FromStr(VAR_LOCALE_USER_DEFAULT)
Double-to-
XML: _VarFromReal -> NodeValueToText -> varDouble:XmlFloatToStrExt -> _VarToDouble -> XmlFloatToStr -> FloatToStr(XmlFormatSettings) -> SetText
Leider ist es nicht möglich, einem Variant/OleVariant eine eigene Locale (FormatSettings) mitzugeben, so das es im Programm überall gleich behandelt wird.
* XMLString-to-Variant und Variant-to-Double macht hier der Variant (sprachabhängig)
* Double-to-Variant macht auch der Variant (sprachabhängig), aber dann Variant-to-XMLString macht die
XML-Komponente (sprach
unabhängig)
XML-Komponente: ist zwar richtig, aber leider falsch, da es beim Auslesen nicht auch so gemacht wird, aber geht auch nicht anders.
Die
XML-Komponente kann nicht einfach den "." im String in ein "," tauschen, damit Variant-to-Double "richtig" arbeiten kann, denn was wäre, wenn der Punkt kein Dezimalpunkt, sondern einfach nur ein Punkt wäre. (z.B. eine Versionsnummer und keine Dezimalzahl)
Delphi-Quellcode:
uses Xml.XMLIntf,
Xml.XMLDoc;
procedure TForm15.FormCreate(Sender: TObject);
var
node: IXMLNode;
doubleValueInput: Double;
doubleValueOutput: Double;
begin
node := NewXMLDocument.GetDocBinding('
Value', TXMLNode, '
')
as IXMLNode;
doubleValueInput := 3.14;
node.NodeValue := doubleValueInput;
doubleValueOutput := node.NodeValue;
Memo1.Text := Format('
DoubleValueInput: %f NodeText: %s, NodeValue: %s, DoubleValueOutput: %f',
[doubleValueInput, node.Text, VarToStr(node.NodeValue), doubleValueOutput])
+ sLineBreak + Node.XML;
end;
Code:
DoubleValueInput: 3,14 NodeText: 3.14, NodeValue: 3.14, DoubleValueOutput: 314,00
<Value>3.14</Value>
Was kommt denn im Seattle raus?
Nja, Hier wirst du wohl oder übel selber den Zahl-String in einen Double konvertieren müssen.
Mit fällt auch keine "gute" Lösung ein, das beim NodeValue reparieren zu können. (außer du stellst dein Windows auf Englisch um oder siehe Tipp)
Delphi-Quellcode:
D := XmlStrToFloat(node.Text);
// oder
D := StrToFloat(node.Text, TFormatSettings.Create('en-US'));
Tipp: Bau dir für IXMLNode einen Record-Helper, welcher ein .AsFloat-Property hat und wo intern in beiden Richtungen gleich gearbeitet wird.
Delphi-Quellcode:
// unit Xml.xmlutil;
function XmlStrToFloat(
const Value:
string): Extended;
function XmlFloatToStr(
const Value: Extended):
string;
function XmlStrToFloatExt(
const Value:
string): Extended;
function XmlFloatToStrExt(
const Value: Extended):
string;
Die ...Ext beachten auch NaN, Infinity und NegInfinity.