Reputation: 5841
I'm reading attribute fields in an XML document where the decimal point always is '.'
and the computer local may differ from this (in my own case it is ','
).
I tried to set the global FormatSettings.DecimalSeparator
to '.'
but it has no effect on the XML parser. This is a very compressed version of the problem.
_di_IXMLDocument Document;
_di_IXMLNode Node;
float Value;
Document = LoadXMLDocument("Test.xml");
Node = Document->DocumentElement;
FormatSettings.DecimalSeparator = '.';
Value = Node->GetAttribute("scale");
Assume this XML file.
<?xml version="1.0" encoding="utf-8"?>
<myroot scale="1.234">
</myroot>
After reading the attribute scale I always get the result striped on the '.' character resulting in Value = 1234 instead of 1.234.
The number of decimals are not constant, they can be 1 or 4 or anything in between. This also goes for the whole part, so dividing by 100 or 1000 will not solve the problem.
I would preferable have the OLEVariant to accept the '.'
as a decimal point (my local is ','
).
I had a look at SetLocalInfo()
but this will set the format for ALL applications. The getlocale()
function manipulates the current thread but I have not found a way to explicitly specify the character to use. It seems like it is only possible to select a code page or localization, as in a country.
EDIT
I tried to use setlocal()
and select English-US
as localization. Even if US are using '.'
as the decimal separator, the XML Parsers seems to ignore this.
If I manually change the '.'
to a ','
in the XML file, it works fine. But the XML file is a third party file, which I have no control of. So I really need to read it as it is with a '.'
decimal separator
Upvotes: 0
Views: 3450
Reputation: 598194
This is a well-known problem with the way the IXMLNode.NodeValue
property handles floating-point numbers. It has nothing to do with the underlying XML engine (MSXML, etc).
The NodeValue
property getter returns an OleVariant
that contains the attribute value as a String
, not as a float
. You are then assigning that OleVariant
to a float
. The RTL performs a conversion using OS locale settings, not RTL locate settings, which is why FormatSettings
has no effect.
The NodeValue
property setter receives an OleVariant
as input. Passing a float
directly to it performs a conversion to a String
when inserting the value into the XML DOM, and that conversion is also not tied to FormatSettings
.
NodeValue
is locale-sensitive, but XML is not. The XML standard specifically outlines exactly how floating-point numbers must be formatted, which IXMLNode
does not take into account. So you will have to read/write floating-point values as String
values so that you can handle conversions yourself, eg:
TFormatSettings fmt = TFormatSettings::Create();
fmt.DecimalSeparator = '.';
fmt.ThousandSeparator = 0;
Value = StrToFloat(Node->Attributes["scale"], fmt);
TFormatSettings fmt = TFormatSettings::Create();
fmt.DecimalSeparator = '.';
fmt.ThousandSeparator = 0;
Node->Attributes["scale"] = FloatToStr(Value, fmt);
Upvotes: 4