Link to home
Start Free TrialLog in
Avatar of Stef Merlijn
Stef MerlijnFlag for Netherlands

asked on

XML encoding is not added

Hi,

I'm using following code to create an XML. But the Encoding isn't added to the XML. This did work nicely previously, but now it isn't anymore?
How can I solve this?

  Doc := NewXMLDocument;
  Doc.Version  := '1.0';
  Doc.Encoding := 'utf-8';
  TijdelijkeString := Doc.XML.Text;

Open in new window


The XML should look like:
<?xml version="1.0" encoding="UTF-8"?>
Avatar of MerijnB
MerijnB
Flag of Netherlands image

I'm not really used to using MSXML (for Dephi I use a third party XML library), but it seems the encoding attribute is only added if you set it to something different then UTF-8. If I change your code to:
  Doc := NewXMLDocument;
  Doc.Version  := '1.0';
  Doc.Encoding := 'utf-16';

Open in new window


the encoding attribute is added, it almost looks like default MSXML behaviour. Why do you need it to be there?

(en de groeten :p)
Please note - activate xml document first:

var
  Xml: IXmlDocument;
begin
  CoInitialize(nil);
  try
    Xml := NewXMLDocument;
    Xml.Active := True;
    Xml.Options := Xml.Options + [doNodeAutoIndent];
    Xml.ParseOptions := Xml.ParseOptions + [poPreserveWhiteSpace];
    Xml.Encoding := 'UTF-8';
    ShowMessage(Xml.XML.Text);
  finally
    CoUninitialize;
  end;

Open in new window

@sinisav, check the implementation of NewXMLDocument()

function NewXMLDocument(Version: DOMString = '1.0'): IXMLDocument;
begin
  Result := TXMLDocument.Create(nil);
  Result.Active := True;
  if Version <> '' then
    Result.Version := Version;
end;

Open in new window


As you can see, it sets active to true for you :)

When I test your code here, there is still no encoding attribute added.
Avatar of Stef Merlijn

ASKER

MerlijnB: The XML must be build up in a certain way, as it is described in the SEPA documentation. They apparently require the encoding.
Sinisav: Your code gives the same result here:

<?xml version="1.0"?>
in stead of
<?xml version="1.0" encoding="UTF-8"?>
It's a strange behaviour. Even when I manually add the encoding it still drops of after I load the string to XML.
    sDoc := Doc.XML.Text;
    sDoc := StringReplace(sDoc, 'encoding="utf-16"', 'encoding="utf-8"', [rfReplaceAll]);
    Doc := LoadXMLData(sDoc);

Open in new window


Found this code in XMLDoc:
function XMLStringToUnicodeString(const XMLString: AnsiString): UnicodeString;
const
  AnsiEncodings: array[0..1] of string = ('ISO-8859-1', 'US-ASCII');
  UnicodeEncodings: array[0..2] of string = ('UTF-16', 'UCS-2', 'UNICODE');
var
  Encoding: string;
begin
  Encoding := ExtractAttrValue(SEncoding, Copy(string(XMLString), 1, 50), '');
  { No Encoding is assumed to be UTF-8 }
  if (Encoding = '') or SameText(Encoding, 'UTF-8') then
    Result := UTF8ToString(XMLString)
  { Latin1 and ASCII can use standard AnsiString->UnicodeString conversion }
  else if EncodingMatches(Encoding, AnsiEncodings) then
    Result := string(XMLString)
  else
  { All others fail }
    XMLDocError(SUnsupportedEncoding, [Encoding]);
  CheckEncoding(Result, UnicodeEncodings);
end;

Open in new window


So I guess it is the default XML-encoding as MerijnB has mentioned.
It is still strange that I was able to add the 'utf-8' encoding before???
@DelphiWizard

for some reason this seems to be a workaround:

var xml: IXMLDocument;
    s: utf8string;
begin
 Xml := NewXMLDocument;
 Xml.Options := Xml.Options + [doNodeAutoIndent];
 Xml.ParseOptions := Xml.ParseOptions + [poPreserveWhiteSpace];
 Xml.Encoding := 'UTF-8';
 XML.SaveToXML(s);
end;

Open in new window


Note that s is an utf8string! If you change it to a normal string it stops working.

Alternatively you could check out 3th party libraries (like SimDesign's TNativeXML: http://www.simdesign.nl/xml.html)
MerijnB: Which external XML library do you use?
I guess it depends on delphi version. In newer delphi strings are unicode (and not utf8), so there is no encoding in your app, but I have it (D6). So, this utf8string is good as is ansistring too in your example.
@DelphiWizard, we use TNativeXML
MerijnB: Your code produces the same result.
I guess    Doc := LoadXMLData(sDoc);
Removes the utf-8 encoding in the end.
Why do you call LoadXMLData() ?

To get the XML, just do  XML.SaveToXML(s), where s is an UTF8string
After building the whole XMl, I need to replace a string.
var sDoc : UTF8String;
begin
    sDoc := Doc.XML.Text;
    sDoc := StringReplace(sDoc, '<CstmrDrctDbtInitn xmlns="">', '<CstmrDrctDbtInitn>', [rfReplaceAll]);
    Doc := LoadXMLData(sDoc);
    Doc.SaveToFile(ExportMap + 'SEPA XML ' + FormatDateTime('yyyy-mm-dd',Date) + '.xml');
end;

Open in new window

Where do you assign content to var "s"?
ASKER CERTIFIED SOLUTION
Avatar of MerijnB
MerijnB
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Looks good, however this is not working.

    // get the XML data in a utf-8 string to force utf-8 attribute
    sTemp := Doc.SaveToXML(sTemp);

Incompatible types: 'UTF8String' and 'procedure, untyped pointer or untyped parameter'
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Perfect, thank you very much.
To be complete:
Creating the file can be as easy as:
TFile.WriteAllText('c:\somefile.xml', sDoc);  // uses IOUtils

Open in new window