I have the following problem:
I have a table with 5000 random generated demo data sets
I would now like to export this one line at a Xliff file.
So the end result should look like. Small example
<?xml version='1.0' encoding='utf-8'?>
<xliff version="1.1">
<file original="source\simple.htm" source-language="EN" target-language="DE" datatype="html">
<header>
<skl>
<external-file uid="017dbcf0-c82c-11e2-ba2b-005056c00008" href="skl\simple.htm.skl"/>
</skl>
</header>
<body>
<trans-unit id="00QlKZsL6GyW6B92Ev81Fb2HP3Z0ma">
<source xml:lang="EN">2hH3khJvy1gmFNTLSB0Crka0A8TTKReuYxbV2hI9E8AjXwCV3F</source>
<target xml:lang="DE">3ydQZWavaKvxrlbh1ewXZakLL00LEPG6zVTyty6fiLrPdx9UE4</target>
<note/></trans-unit>
<trans-unit id="016ynILnditynwtYwcl6vJPTLCzvo7">
<source xml:lang="EN">dyC28VRCI9O37PTHENinp4sgMkr5R0HO1Yo53hUQKNr4GoLFG4</source>
<target xml:lang="DE">sEkgstffmS4k5KB1JZkNSYbUnzzlFBNT30oYmtfId8dnspG3No</target>
<note>Testnotiz</note></trans-unit>
<trans-unit id="03YNBAZ1YWvkqaG4PRxKSiWENOCXuB">
<source xml:lang="EN">BHpY8LDs8oJAr8I1EfZzeJX24GZ3TLIr9GUAYcnSPYHjDfKRqk</source>
<target xml:lang="DE">7Rd7bW2lg2Uc4uStCoosZuNgOzA9qWN7OsvW2gBcHa3ctnmF3Q</target>
<note/></trans-unit>
</body>
</file>
</xliff>
As a component of the Edit / Paste Xliff the file I wanted to grab my XMLDocument. I already had a few days ago wrote a demo program where I upload a file using XMLDocument and then Xliff purely write something again. So these routines at least for the targets I already have.
I feel now more that I still have no real idea how all the data from the MySQL table as the best piece of land in a Xliff file pack.
First thought was possible for me to go through the entire table line by line, then save it into an array and then write my loop over the array and in the file.
Would appreciate some other suggestions / concepts. Since it is a test of the speed of the XMLDocument component in the end I would concepts / ideas that lead to a rapid course prefer.
Here a solution using the Strategy Design Pattern to have an easy extendable solution for various export strategies (XML Plain or XmlDoc, CSV, ...)
Base Document
unit Document;
interface
type
TDocument = class;
IDocumentExportFileStrategy = interface
['{787B60E5-A3CA-485C-A46E-248A43D7175C}']
procedure ExportDoc( AContext : TDocument; const AFileName : string );
end;
TDocument = class
private
FExportFileStrategy : IDocumentExportFileStrategy;
protected
function GetValue( const Name : string ) : Variant; virtual; abstract;
public
procedure First; virtual; abstract;
procedure Next; virtual; abstract;
function Eof : Boolean; virtual; abstract;
property Value[const Name : string] : Variant read GetValue;
property ExportFileStrategy : IDocumentExportFileStrategy read FExportFileStrategy write FExportFileStrategy;
procedure ExportTo( const AFileName : string );
end;
implementation
{ TDocument }
procedure TDocument.ExportTo( const AFileName : string );
begin
FExportFileStrategy.ExportDoc( Self, AFileName );
end;
end.
An Xliff export strategy writing plain text for fast execution
unit XliffPlainExporter;
interface
uses
Document,
SysUtils, Variants,
Classes;
type
TXliffPlainExporter = class( TInterfacedObject, IDocumentExportFileStrategy )
private
procedure WriteLine( AStream : TStream; ALine : string );
protected
procedure WriteHead( AContext : TDocument; AStream : TStream );
procedure WriteDetails( AContext : TDocument; AStream : TStream );
procedure WriteFoot( AContext : TDocument; AStream : TStream );
public
procedure ExportDoc( AContext : TDocument; const AFileName : string );
end;
implementation
{ TXliffPlainExporter }
procedure TXliffPlainExporter.ExportDoc( AContext : TDocument; const AFileName : string );
var
LStream : TStream;
LFileName : string;
begin
AContext.First;
if not AContext.Eof
then
begin
LFileName := AFileName;
if ExtractFileExt( LFileName ) = ''
then
LFileName := ChangeFileExt( LFileName, '.xml' );
LStream := TFileStream.Create( LFileName, fmCreate );
try
WriteHead( AContext, LStream );
WriteDetails( AContext, LStream );
WriteFoot( AContext, LStream );
finally
LStream.Free;
end;
end;
end;
procedure TXliffPlainExporter.WriteHead( AContext : TDocument; AStream : TStream );
begin
WriteLine( AStream, '<?xml version=''1.0'' encoding=''utf-8''?>' );
WriteLine( AStream, '<xliff version="1.1">' );
WriteLine( AStream, ' <file original="source\simple.htm" source-language="EN" target-language="DE" datatype="html">' );
WriteLine( AStream, ' <header>' );
WriteLine( AStream, ' <skl>' );
WriteLine( AStream, ' <external-file uid="017dbcf0-c82c-11e2-ba2b-005056c00008" href="skl\simple.htm.skl"/>' );
WriteLine( AStream, ' </skl>' );
WriteLine( AStream, ' </header>' );
WriteLine( AStream, ' <body>' );
end;
procedure TXliffPlainExporter.WriteDetails( AContext : TDocument; AStream : TStream );
begin
while not AContext.Eof do
begin
WriteLine( AStream, Format( ' <trans-unit id="%s">', [VarToStr( AContext.Value['id'] )] ) );
WriteLine( AStream, Format( ' <source xml:lang="EN">%s</source>', [VarToStr( AContext.Value['src'] )] ) );
WriteLine( AStream, Format( ' <target xml:lang="DE">%s</target>', [VarToStr( AContext.Value['dst'] )] ) );
WriteLine( AStream, ' <note/></trans-unit>' );
AContext.Next;
end;
end;
procedure TXliffPlainExporter.WriteFoot( AContext : TDocument; AStream : TStream );
begin
WriteLine( AStream, ' </body>' );
WriteLine( AStream, ' </file>' );
WriteLine( AStream, '</xliff>' );
end;
procedure TXliffPlainExporter.WriteLine( AStream : TStream; ALine : string );
var
LLine : TStream;
begin
LLine := TStringStream.Create( ALine + sLineBreak, TEncoding.UTF8 );
try
LLine.Position := 0;
AStream.CopyFrom( LLine, LLine.Size );
finally
LLine.Free;
end;
end;
end.
Simple Test-Document just for testing purpose
unit TestDocument;
interface
uses
Document;
type
TTestDocument = class( TDocument )
private
FIndex : Integer;
protected
function GetValue( const Name : string ) : Variant; override;
public
function Eof : Boolean; override;
procedure First; override;
procedure Next; override;
end;
implementation
uses
SysUtils,
StrUtils;
{ TTestDocument }
function TTestDocument.Eof : Boolean;
begin
Result := FIndex >= 100;
end;
procedure TTestDocument.First;
begin
inherited;
FIndex := 0;
end;
function TTestDocument.GetValue( const Name : string ) : Variant;
begin
case IndexText( Name, ['id', 'src', 'dst'] ) of
0 :
Result := Format( 'id%8.8d', [FIndex + 1] );
1 :
Result := Format( 'src%8.8d', [FIndex + 1] );
2 :
Result := Format( 'dst%8.8d', [FIndex + 1] );
end;
end;
procedure TTestDocument.Next;
begin
inherited;
Inc( FIndex );
end;
end.
And putting the pieces together
program DataExportStrategy;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Document in 'Document.pas',
TestDocument in 'TestDocument.pas',
XliffPlainExporter in 'XliffPlainExporter.pas';
procedure Test;
var
LDoc : TDocument;
begin
LDoc := TTestDocument.Create;
try
LDoc.ExportFileStrategy := TXliffPlainExporter.Create;
LDoc.ExportTo( 'test' );
finally
LDoc.Free;
end;
WriteLn( 'Export finished' );
end;
begin
try
Test;
except
on E : Exception do
WriteLn( E.ClassName, ': ', E.Message );
end;
ReadLn;
end.
In your case, you would like to have a document based on a DataSet so you implement a TDataSetDocument
unit DataSetDocument;
interface
uses
Document,
Data.DB;
type
TDataSetDocument = class( TDocument )
private
FDataSet : TDataSet;
protected
function GetValue( const Name : string ) : Variant; override;
public
constructor Create( ADataSet : TDataSet );
function Eof : Boolean; override;
procedure Next; override;
procedure First; override;
end;
implementation
{ TDataSetDocument }
constructor TDataSetDocument.Create( ADataSet : TDataSet );
begin
inherited Create;
FDataSet := ADataSet;
end;
function TDataSetDocument.Eof : Boolean;
begin
Result := FDataSet.Eof;
end;
procedure TDataSetDocument.First;
begin
inherited;
FDataSet.First;
end;
function TDataSetDocument.GetValue( const Name : string ) : Variant;
begin
Result := FDataSet.FieldByName( Name ).Value;
end;
procedure TDataSetDocument.Next;
begin
inherited;
FDataSet.Next;
end;
end.
and use it
var
LDoc : TDocument;
LDoc := TDataSetDocument.Create( MyQuery );
try
LDoc.ExportStrategy := TXliffPlainExporter.Create;
LDoc.ExportTo( 'test' );
finally
LDoc.Free;
end;