Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Datensätze aus Tabelle holen und in Datei speichern (https://www.delphipraxis.net/175076-datensaetze-aus-tabelle-holen-und-datei-speichern.html)

Back2Code 29. Mai 2013 09:24

Datenbank: MySQL • Version: 50529 • Zugriff über: UniDac

Datensätze aus Tabelle holen und in Datei speichern
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe folgendes Problem:

Ich habe eine Tabelle mit 5000 Zufällig generierten Demo Datensätzen

http://www.delphipraxis.net/attachme...1&d=1369815195

Diese möchte ich jetzt Zeile für Zeile in eine Xliff Datei exportieren.

So sollte dann das Endergebnis aussehen. Kleines Beispiel

Code:
<?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>
Als Komponente für das Bearbeiten/Einfügen der Xliff Datei wollte ich mir XMLDocument schnappen. Hatte mir schon vor ein paar Tagen ein Demoprogramm geschrieben wo ich per XMLDocument eine Xliff Datei lade und anschließend auch wieder etwas reinschreibe. Also diese Routinen zumindestens für die Targets habe ich bereits.

Es geht mir jetzt vielmehr darum, dass ich noch keine richtige Idee habe wie die ganzen Daten aus der MySQL Tabelle am besten Szück wie Stück in eine Xliff Datei packe.

Erster Gedanke war von mir eventuell, durch die komplette Tabelle Zeile für Zeile zu gehen, diese dann in ein Array zu speichern und dann per Schleife drüberzugehn und in die Datei zu schreiben.

Würde mich über ein paar andere Vorschläge / Konzepte freuen. Da es im Endeffekt um einen Test von der Geschwindigkeit der XMLDocument Komponenete geht wären mir Konzepte / Ideen die zu einem schnellen Ablauf führen am liebsten.

nahpets 29. Mai 2013 20:24

AW: Datensätze aus Tabelle holen und in Datei speichern
 
Wenn ich das recht sehe, benötigst Du für jede Zeile Deiner Tabelle diesen Part:
Code:
      <trans-unit id="016ynILnditynwtYwcl6vJPTLCzvo7">
        <source xml:lang="EN">dyC28VRCI9O37PTHENinp4sgMkr5R0HO1Yo53hUQKNr4GoLFG4</source>
        <target xml:lang="DE">sEkgstffmS4k5KB1JZkNSYbUnzzlFBNT30oYmtfId8dnspG3No</target>
      <note>Testnotiz</note></trans-unit>
Es ist nicht erforderlich die Tabelle erst in ein Array zu schreiben und dann dieses in die Datei zu exportieren.
Die Tabelle ist letztlich auch nichts Anderes, als ein Array, welches Du zeilenweise abarbeiten kannst.

Mal so (ohne zu prüfen) hingedaddelt:
Delphi-Quellcode:
begin
  tabelle.First;
  while not tabelle.EoF do begin
     AddNode(tabelle.FieldByName('ID').AsString,
             tabelle.FieldByName('src').AsString,
             tabelle.FieldByName('dst').AsString)
    tabelle.Next;
  end;
end;
Zitat:

Zitat von Polymorphin
Also diese Routinen zumindestens für die Targets habe ich bereits.

AddNode wäre hier also diese Routine, die die drei Parameter aus der Datenbank entsprechend verarbeitet und die Targets quasi zeilenweise in die Datei einfügt.

jensw_2000 29. Mai 2013 20:39

AW: Datensätze aus Tabelle holen und in Datei speichern
 
Genau. Datensatzweise durchlaufen und direkt mit AddNode in die XML Datei schreiben ist perfekt.
Wenn Du die Tabelle dann noch Readonly öffnest (und falls unterstützt mit einem "ForwardOnly" Cursor), dann ist der Export auch fix erledigt.
Abhängig von den verwendeten DB Komponenten musst du darauf achten, dass tatsächlich alle Datensätze beim Öffnen der Tabelle gefetcht werden.

Sir Rufo 30. Mai 2013 01:27

AW: Datensätze aus Tabelle holen und in Datei speichern
 
Crosspost: http://stackoverflow.com/questions/1...d-save-to-file

Back2Code 3. Jun 2013 07:39

AW: Datensätze aus Tabelle holen und in Datei speichern
 
Zitat:

Zitat von Sir Rufo (Beitrag 1216936)

Da konnte mir leider niemand weiterhelfen. Den oben beschriebenen Ansatz werde ich ausprobieren

Sir Rufo 3. Jun 2013 08:09

AW: Datensätze aus Tabelle holen und in Datei speichern
 
Zitat:

Zitat von Polymorphin (Beitrag 1217317)
Zitat:

Zitat von Sir Rufo (Beitrag 1216936)

Da konnte mir leider niemand weiterhelfen. Den oben beschriebenen Ansatz werde ich ausprobieren

Wieso konnte dir da nicht geholfen werden?
Es gibt zwar nur einen Kommentar, aber der trifft doch genau ins Schwarze?
Oder willst du direkt Code haben?

Sir Rufo 3. Jun 2013 09:10

AW: Datensätze aus Tabelle holen und in Datei speichern
 
Also hierfür bietet sich das Strategy Design Pattern an.

Hier eine beispielhafte Umsetzung

Delphi-Quellcode:
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.
Die Export-Strategie für Xliff (Plain-Text)
Delphi-Quellcode:
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

{ TXmlExporter }

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.
Ein konkretes Test-Dokument
Delphi-Quellcode:
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.
und das Hauptprogramm zum Testen
Delphi-Quellcode:
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.
Wenn du ein
Delphi-Quellcode:
TDataSetDocument
benötigst, dann bau es dir so
Delphi-Quellcode:
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.
und fertig ...

Benötigst du weitere (oder anders funktionierende) Export-Formate (z.B. CSV oder XML mit XMLDoc), dann einfach eine neue Strategie-Klasse implemetieren, dem Document zuweisen und Exportieren lassen. ;)


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:00 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz