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"?>
Stef MerlijnDeveloperAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

MerijnBSr. Software EngineerCommented:
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)
0
Sinisa VukSoftware architectCommented:
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

0
MerijnBSr. Software EngineerCommented:
@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.
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

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

<?xml version="1.0"?>
in stead of
<?xml version="1.0" encoding="UTF-8"?>
0
Stef MerlijnDeveloperAuthor Commented:
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???
0
MerijnBSr. Software EngineerCommented:
@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)
0
Stef MerlijnDeveloperAuthor Commented:
MerijnB: Which external XML library do you use?
0
Sinisa VukSoftware architectCommented:
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.
0
MerijnBSr. Software EngineerCommented:
@DelphiWizard, we use TNativeXML
0
Stef MerlijnDeveloperAuthor Commented:
MerijnB: Your code produces the same result.
I guess    Doc := LoadXMLData(sDoc);
Removes the utf-8 encoding in the end.
0
MerijnBSr. Software EngineerCommented:
Why do you call LoadXMLData() ?

To get the XML, just do  XML.SaveToXML(s), where s is an UTF8string
0
Stef MerlijnDeveloperAuthor Commented:
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"?
0
MerijnBSr. Software EngineerCommented:
I'd suggest you don't use doc again to save the file to disk, see example.
Please note that StringToFile() is not an existing function, but you'll probably be able to whip up something :)

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

    // copy it to a normal string
    sDoc := sTemp;

    // do some nifty replacement
    sDoc := StringReplace(sDoc, '<CstmrDrctDbtInitn [b]xmlns=""[/b]>', '<CstmrDrctDbtInitn>', [rfReplaceAll]);

    // now save sDoc to a filemanually, without giving it back to Doc again
    StringToFile('c:\somefile.xml', sDoc);
end;

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Stef MerlijnDeveloperAuthor Commented:
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'
0
MerijnBSr. Software EngineerCommented:
oops, it's just
Doc.SaveToXML(sTemp);

Open in new window

0
Stef MerlijnDeveloperAuthor Commented:
Perfect, thank you very much.
0
Stef MerlijnDeveloperAuthor Commented:
To be complete:
Creating the file can be as easy as:
TFile.WriteAllText('c:\somefile.xml', sDoc);  // uses IOUtils

Open in new window

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.