4

I am using Delphi7 TClientDataSet to read and write XML files for some of my data.

However, when I want to browse this outside the program (double clicking the XML in Windows Explorer) I get the 'An invalid character was found in text content. Error processing resource' - even though the data reads and writes fine from within Delphi.

Is there a way to force TClientDataSet to write its contents in an indented way instead of in one line?

That way I could easily open it into a text editor and find what character will trigger the above error.

Anyway: I find it much clearer for an XML file to be written with CR/LF and indents anyway.

Andreas Rejbrand
  • 105,602
  • 8
  • 282
  • 384
Edelcom
  • 5,038
  • 8
  • 44
  • 61
  • -1. It's unclear how indenting the XML will solve the invalid-character problem. Please clarify what problem you want to solve. If you have two problems, then please post *two* questions. – Rob Kennedy Oct 03 '10 at 19:10
  • @Rob Kennedy: Have you ever tried to edit an xml file with a text editor where the whole file is on one line ? If the file is indented, and therefore using cr/lf as line seperator, you can easily load it up in an editor and at least visually view the file to look for the culprit character (or characters). Where do you see two questions ? I asked whether it was possible to force the TClientDataset to write an indented xml-formatted file. The error was to clarify why I needed this. The title of the question says was I was asking, no ? The -1 here is unneeded. – Edelcom Oct 04 '10 at 06:13
  • I would have to agree with Rob here, because almost all development environments have an option to automatically format XML code. Even if you don't, there are plenty websites out there which can help you format your code. Tweaking a very common database component in Delphi to do something it wasn't built to do is a bit overboard for your situation. It's also unclear whether you want your bug fixed or if you want to make the clientdataset save indented XML. – Jerry Dodge Sep 09 '13 at 04:31

4 Answers4

8

When you uses the TCustomClientDataSet.SaveToFile procedure, you can choose the output format, for default this value is set to dfBinary wich encode the data in a binary format.

 procedure TCustomClientDataSet.SaveToFile(const FileName: string = '';
  Format: TDataPacketFormat = dfBinary);

try changing the Format parameter to dfXML or dfXMLUTF8

ClientDataSet1.SaveToFile('file.xml',dfXML);

if you want format the XML output you can use the FormatXMLData function try this code

uses
 XMLDoc;

Procedure FormatXMLFile(XmlFile:string);
var
   oXml : TXMLDocument;
 begin
   oXml := TXMLDocument.Create(nil);
   try
     oXml.LoadFromFile(XmlFile);
     oXml.XML.Text:=xmlDoc.FormatXMLData(oXml.XML.Text);
     oXml.Active := true;
     oXml.SaveToFile(XmlFile);
   finally
     oXml := nil;
   end;
 end;

finally you code will look like this

 ClientDataSet1.SaveToFile('test.xml',dfXML);
 FormatXMLFile('test.xml');
RRUZ
  • 134,889
  • 20
  • 356
  • 483
  • 2
    Beware that if the data contains characters 'çé...' like in `François`, saving as `dfXML` is not enough, `dfXMLUTF8` is required. – Francesca Oct 03 '10 at 18:32
4

It's because the proper encoding (like <?xml version="1.0" encoding="UTF-8"?>) has not be specified in your output file, yet it contains some characters with an incompatible encoding.

As RRUZ mentioned, specifying explicitly the TDataPacketFormat as dfXMLUTF8 when writing the file will most certainly solve the 'Invalid Character' error, as it will write the encoding tag first:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <DATAPACKET Version="2.0">[...]
You can also add the encoding manually at the beginning of the file for already existing files.

As for the readable formatting, some readers can read the raw one-liner and do the formatting for you (browsers like FireFox or Internet Exporer, and XML editors like XMLNotePad)

Community
  • 1
  • 1
Francesca
  • 21,452
  • 4
  • 49
  • 90
1

I modified your code, because I had some problems with UTF-8:

Procedure FormatXMLFile(XmlFile:string);
var
   oXml : TXMLDocument;
   s : utf8String;
begin
   oXml := TXMLDocument.Create(nil);
   try
     oXml.LoadFromFile(XmlFile);
     s :=  oxml.XML.Text;
     s  := StringReplace(s, '><', '>' + #13#10 + '<' , [rfReplaceAll]);
     //oXml.XML.Text:=xmlDoc.FormatXMLData(oxml.XML.Text);
     oxml.XML.Text := s;
     oXml.Active := true;
     oXml.SaveToFile(XmlFile);
   finally
     oXml := nil;
   end;
end;
showdev
  • 28,454
  • 37
  • 55
  • 73
0

dfXMLUTF8 use it for UTF

ClientDataSet1.SaveToFile('test.xml',dfXMLUTF8)

Pit
  • 395
  • 2
  • 11