Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   XML (https://www.delphipraxis.net/46-xml/)
-   -   Delphi Wie in XML-Datei sortieren? (https://www.delphipraxis.net/46747-wie-xml-datei-sortieren.html)

toko 30. Mai 2005 20:33


Wie in XML-Datei sortieren?
 
Hallo,

ich bin es mal wieder. Ich kann nun sauber in meiner XML-Datei Knoten/Attribute lesen und schreiben.
(Danke noch mal an MathiasSimmack :thumb: )
Die Daten schreibe ich dabei durch meine Anwendung sofort in diese Datei:
XML-Code:
<?xml version="1.0"?>
<cdorganizer>
   <cd id="1" titel="g testcd1" interpret="testinterpret1" genre="genre1">
   <track id="1" titel="testtrack1" interpret="testinterpret1" dauer="11:11:11"/>
   <track id="2" titel="testtrack2" interpret="testinterpret2" dauer="11:11:12"/>
   <track id="3" titel="testtrack3" interpret="testinterpret3" dauer="11:11:13"/>
   <track id="4" titel="testtrack4" interpret="testinterpret4" dauer="11:11:14"/>
   <track id="5" titel="testtrack5" interpret="testinterpret5" dauer="11:11:15"/>
   </cd>
   <cd id="2" titel="f testcd2" interpret="testinterpret2" genre="genre2"></cd>
   <cd id="3" titel="e testcd3" interpret="testinterpret3" genre="genre3"></cd>
   <cd id="4" titel="d testcd4" interpret="testinterpret4" genre="genre4"></cd>
   <cd id="5" titel="c testcd5" interpret="testinterpret5" genre="genre5"></cd>
   <cd id="6" titel="b testcd6" interpret="testinterpret6" genre="genre6"></cd>
   <cd id="7" titel="a testcd7" interpret="testinterpret7" genre="genre7"></cd>
</cdorganizer>
In der Anwendung selbst werden die CD's dann in einem TStringGrid dargestellt. In einem zweiten TStringGrid werden zu einer markierten CD die Tracks dargestellt.
Ich möchte nun die Daten alphabetisch sortieren.

Geht das ohne Benutzung von Listen? Wenn ja, bin ich für jeden Tipp sehr dankbar. Wenn nein, dann hab ich das Problem der Listenbenutzung hier versucht zu beschreiben.
Kann ich eventuell den Sortieralgorithmus "Sort" von TStringList/TList verwenden?
Mir stellt sich jedoch die Frage, was dann mit der/den Liste/Kindknoten zu einer CD passiert?

Falls ich mich unverständlich ausdrücke, bitte ruhig melden, dann erläutere ich das Thema genauer.

Gruß

[edit=Matze]Beitrag aufgrund eines Caching-Fehlers neu abgesendet. MfG, Matze[/edit]

MathiasSimmack 30. Mai 2005 20:51

Re: Wie in XML-Datei sortieren?
 
Was möchtest du sortieren? Die Daten im Programm? Oder die Daten in der XML-Datei?

toko 30. Mai 2005 22:50

Re: Wie in XML-Datei sortieren?
 
:gruebel: wenn ich so recht überlege brauche ich gar nicht die Daten in der XML-Datei zu sortieren, sondern nur die im TStringGrid.
Es soll mit der Sortierung einfach nur eine übersichtlichere Art des Lesens erreicht werden.

Ok, also ich möchte die Daten im Programm sortieren.

marabu 31. Mai 2005 08:02

Re: Wie in XML-Datei sortieren?
 
Hallo toko,

deine über DOM zugänglichen internen XML-Daten könntest du mit XSLT umsortieren. Dazu musst du nur xsl:sort in eine identity transformation verpacken. So sieht das dann aus, wenn du nach "titel" sortieren willst:

Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

  <xsl:template match="/ | @* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()">
        <xsl:sort select="@titel"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
Wenn deine XML-Daten in xmlDoc bereit stehen und dieses Skript in xmlStyle, dann wird die Sortierung deiner XML-Daten durch folgenden Aufruf durchgeführt:

Delphi-Quellcode:
xmlDoc.loadXML(xmlDoc.transformNode(xmlStyle));
Grüße vom marabu

alcaeus 31. Mai 2005 08:05

Re: Wie in XML-Datei sortieren?
 
Zitat:

Zitat von toko
:gruebel: wenn ich so recht überlege brauche ich gar nicht die Daten in der XML-Datei zu sortieren, sondern nur die im TStringGrid.

Ganz genau. Und wenn du statt dem StringGrid auch noch eine ListView verwendest, kannst du mit Hilfe dieses Codes die Sortierung waehrend der Laufzeit aendern. Die Anordnung der Daten in der Datei sollte naemlich nichts mit jener im Programm zu tun haben, jedenfalls nicht bei deinem Beispiel ;)

Greetz
alcaeus

toko 31. Mai 2005 09:54

Re: Wie in XML-Datei sortieren?
 
Hi,

danke für eure Beiräge. Ich werde beide Variante mal heute abend probieren :coder: . Ich lasse jedoch dieses Thema so lange offen, falls sich noch meinerseits Fragen ergeben.

Gruß

toko 31. Mai 2005 23:40

Re: Wie in XML-Datei sortieren?
 
Hallo,

@alcaeus
Ich habe mir überlegt erst mal die Variente von marabu zu probieren. Da es eine Forderung ist meine Daten in einem TStringGrid darzustellen.
Da ich auch ziemlich weit mit der Programmierung fortgeschritten bin, ist es etwas mühsam die Grids und die darauf aufbauenden Funktionen auf ListViews umzustellen. Ich behalte es aber im Hinterkopf.

@marabu
Zitat:

Dazu musst du nur xsl:sort in eine identity transformation verpacken.
:wiejetzt: Wie mache ich das genau? Wo muss ich diesen Code
Delphi-Quellcode:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

  <xsl:template match="/ | @* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()">
        <xsl:sort select="@titel"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
abspeichern? Muss ich dafür eine .XSL-Datei mit selben Namen wie die XML-Datei anlegen?

Mit
Delphi-Quellcode:
xmlDoc.load(xmlfile);
lade ich übrigens meine XML-Datei. In xmlfile steht der Pfad der Datei.

Wo ist den der Unterschied zwischen "load" und "loadXML". Bei "loadXML" bekomme ich einen parseError.

Kannst du deine quasi-Anleitung etwas genauer beschreiben?
Danke...

Gruß ToKo

[edit=Matze]Beitrag aufgrund eines Caching-Fehlers neu abgesendet. MfG, Matze[/edit]

marabu 1. Jun 2005 06:49

Re: Wie in XML-Datei sortieren?
 
Hallo ToKo,

voraus schicken möchte ich, dass ich dir bei einem Teilproblem im XML-Bereich helfe, dir aber für dein Projekt wahrscheinlich einen Bärendienst erweise. Du sprichst von Anforderungen, aber es ist mir nicht klar, wer die formuliert hat - du selbst oder ein anderer. Ich fürchte, dass es einfach nur Entscheidungen sind, die du vor deinem persönlichen Erfahrungshorizont getroffen hast. Ich würde einen CD-Manager voll in die Windows Shell integrieren und das Speicherformat hätte ich wahrscheinlich von FreeDB übernommen.
Der lockere Hinweis von alcaeus an dich enthält einen Wink mit dem Zaunpfahl: Wenn du alle Funktionalität in dein Stringgrid eingebaut haben wirst, dann wird jeder Betrachter sich fragen, warum du nicht gleich eine ListView genommen hast.

Aber das alles ist dein Projekt, sind deine Entscheidungen. Kommen wir zu deinem XML-Problem.

Zitat:

Zitat von toko
Wie mache ich das genau? Wo muss ich diesen Code abspeichern? Muss ich dafür eine .XSL-Datei mit selben Namen wie die XML-Datei anlegen?

Zuerst brauchst du eine zweite Variable xmlStyle neben deiner xmlDoc Variable. Mit xmlDoc hast du deine XML-Daten geladen, xmlStyle nimmt den XSLT-Code auf. Bei mir sind beide vom Typ IXMLDOMDocument. Du musst abwägen, ob du nur eine oder mehrere Sortierungen benötigst. Wenn es nur um die eine Sortierung geht, dann kannst du den XSLT-Code in einer Datei mit der Erweiterung XSL speichern und diese mit xmlStyle.load() laden. Ich empfehle dir aber einen resourcestring fmtXSLsort zu verwenden, in dem du den für die Sortierung ausgewählten Knoten @titel durch %s ersetzt und vor dem Sortieren mit der Anweisung

Delphi-Quellcode:
xmlStyle.loadXML(Format(fmtXSLsort, ['@titel']));
lädst. Hier solltest du erkennen, dass mit load() eine Datei mit einem bestimmten URL geladen wird, während mit loadXML() ein XML-String geladen wird.

Grüße vom marabu

toko 1. Jun 2005 17:56

Re: Wie in XML-Datei sortieren?
 
Hallo marabu,

Zitat:

voraus schicken möchte ich, dass ich dir bei einem Teilproblem im XML-Bereich helfe, dir aber für dein Projekt wahrscheinlich einen Bärendienst erweise.
Das weiß ich ja auch zu schätzen.


Zitat:

Du sprichst von Anforderungen, aber es ist mir nicht klar, wer die formuliert hat - du selbst oder ein anderer. Ich fürchte, dass es einfach nur Entscheidungen sind, die du vor deinem persönlichen Erfahrungshorizont getroffen hast.
Ich programmiere diese Anwendung im Rahmen eines Wahlpflichtfachs meines Studiums, welches auch lediglich nur eine Einführung ist. Dabei hatten wir einige Komponenten und Techniken besprochen, welche wir dann in einer "simplen" CD-Verwaltung benutzen sollten. Unter anderem viel dabei der Satz: "CDs können in einer TStringGrid angezeigt werden. Ein Mausklick in der ersten Reihe einer Spalte bewirkt das Sortieren der TStringGrid nach den Daten in der Spalte." und "CDs können in einer Datei gespeichert werden, und aus dieser Datei eingelesen werden." Das ich dann XML-Dateien benutze, schien mir sinnvoller, als INI-Dateien oder "normale" Textdateien.

Zitat:

Der lockere Hinweis von alcaeus an dich enthält einen Wink mit dem Zaunpfahl: Wenn du alle Funktionalität in dein Stringgrid eingebaut haben wirst, dann wird jeder Betrachter sich fragen, warum du nicht gleich eine ListView genommen hast.
Ich wollte halt erstmal die Variante mit der XML-Sortierung testen, da ich mit der ListView-Komponente noch keine Erfahrungen gesammelt habe. Ich werde mich nachher mal damit auseinandersetzen, ob ich mit der ListView die gleichen(besseren) Eigenschaften/Methoden habe, wie(als) mit dem StringGrid. Ich denke mal, wenn ich eine sinnvollere Komponente als die StringGris eingesetzt habe, dann kann man das gegenüber dem Prof erwähnen. Wobei ich denke, dass er dann auch die Lösung mit ListView favorisieren wird.

Zitat:

Aber das alles ist dein Projekt, sind deine Entscheidungen.
Ich lasse mich gerne eines besseren belehren. Falls das anders angekommen ist, Sorry! Ich weiß, dass ich durch DP eine kompetente und schnelle Hilfe bekomme; und brauche auch so nicht noch mehr Zeit in die Anwendung investieren, als dass ich schon tue.

Wie gesagt, danke für deine/eure Hilfe.

Ich werde nun mal versuchen meine Sortiergeschichte zu lösen...
mfg

marabu 1. Jun 2005 19:07

Re: Wie in XML-Datei sortieren?
 
Zitat:

Falls das anders angekommen ist, Sorry!
Ganz und gar nicht.

Ich hatte ein schlechtes Gewissen bei meinen Vorbemerkungen, da ich unsicher war, wie ich am besten helfen kann.

Ich würde zwar die Benutzer-Oberfläche eher mit einer ListView als mit einem StringGrid gestalten, aber zum Sortieren würde ich die ListView nicht verwenden können, da ich die Daten grundsätzlich in Daten-Containern verwalte und nicht in UI-Controls.

marabu

toko 1. Jun 2005 20:23

Re: Wie in XML-Datei sortieren?
 
Hi,

irgendwie haut das bei mir nicht hin. Ich liste mal etwas ausführlicher meine Schritte auf. Ich habe diesen Code
Delphi-Quellcode:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >

  <xsl:template match="/ | @* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()">
        <xsl:sort select="@titel"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>
in die Datei "sortdata.xsl" im Order, wo sich auch die Anwendung befindet, gespeichert. In meinem Programm löst dies:
Delphi-Quellcode:
xmlStyle.load(FAppPath + 'sortdata.xsl');
eine Exception der Klasse "EAccessViolation" aus. Ich habe mal testweise sortdata.xsl durch data.xml, in der meine XML-Daten liegen, getauscht.
Kein Problem. Es kann dann ja nur daran liegen, dass sortdata eine xsl-Datei ist.

Hab ich was falsch gemacht?

Gruß

[edit=Matze]Beitrag aufgrund eines Caching-Fehlers neu abgesendet. MfG, Matze[/edit]

marabu 1. Jun 2005 20:31

Re: Wie in XML-Datei sortieren?
 
Wie hast du deine Variablen xmlDoc und xmlStyle deklariert, wie initialisiert?
Bist du mal im single step durch den Code gegangen?
Ist xmlStyle eventuell nil?

marabu

toko 1. Jun 2005 20:48

Re: Wie in XML-Datei sortieren?
 
xmlDoc und xmlStyle sind beide vom Typ IXMLDOMDocument2. Initialisiert habe ich die nicht.
Wenn ich durch den Code gehe, dann ist xmlStyle nil. Beim xmlDoc bekomme ich einen Pointer.

Toko

marabu 1. Jun 2005 21:09

Re: Wie in XML-Datei sortieren?
 
Wenn du keinen guten Grund für die Verwendung von IXMLDOMDocument2 hast, dann nimm IXMLDOMDocument. Ich unterstelle, dass du MSXML 4.0 installiert hast. Das Arbeiten mit dieser Schnittstelle sieht dann ungefähr so aus:

Delphi-Quellcode:
var
  xmlStyle: IXMLDOMDocument;
begin
  // erzeugen
  xmlStyle := CoDomDocument.Create;
  // app erhält Kontrolle erst nach vollständigem load()
  xmlStyle.async := false;
  // Erfolg testen
  if xmlStyle.load(fullFilename)
    then ShowMessage('smile')
    else ShowMessage(xmlStyle.parseError.reason);
  // so wird der vom DOM belegte Speicher wieder freigegeben
  xmlStyle := nil;
end;
marabu

toko 1. Jun 2005 21:33

Re: Wie in XML-Datei sortieren?
 
Ich bekomme ein :lol:
Ich hatte vorher das Create vergessen :wall: . Da hätte ich auch selbst drauf kommen können.

Danke...
toko

toko 1. Jun 2005 22:07

Re: Wie in XML-Datei sortieren?
 
Hallo nochmal,

ich hab nun folgende Prozedur:
Delphi-Quellcode:
procedure TfrmMain.sortXMLFile;
var
  xmlStyle: IXMLDOMDocument;
begin
  xmlStyle := CoDomDocument.Create;
  xmlDoc := CoDOMDocument.Create;
  xmlDoc.load(xmlfile);
  xmlStyle.async := false;
  xmlStyle.load(FAppPath + 'data.xsl');
  xmlDoc.load(xmlDoc.transformNode(xmlStyle));
  cds := XMLDoc.documentElement.selectNodes('cd');
  ...
end;
die ich bei einem ButtonClick aufrufe. Meine Daten in der XML-Datei sehen aber immer noch gleich aus.

Hab ich was nicht beachtet?

ToKo

MathiasSimmack 1. Jun 2005 22:24

Re: Wie in XML-Datei sortieren?
 
Die XSL-Datei von marabu sorgt normalerweise nur für die interne Umsortierung der Daten. Die XML-Datei selbst bleibt unverändert, aber das DOM-Objekt deines Programms bekommt so die Daten sortiert geliefert.

toko 1. Jun 2005 23:10

Re: Wie in XML-Datei sortieren?
 
OK, versteh ich. Dann müßte ich doch auch mit dem DomObjekt arbeiten können. D.h. die Zeile:
Delphi-Quellcode:
  cds := XMLDoc.documentElement.selectNodes('cd');
dürfte dann keine EAccessViolationException auslösen.

Beim öffnen einer XML-Datei gehe nämlich genauso vor, um die Daten aus dem DomObjekt ins StringGrid zu übertragen. Und das klappt ohne Probleme. :gruebel:

Gruß
ToKo

marabu 2. Jun 2005 06:26

Re: Wie in XML-Datei sortieren?
 
Zitat:

Zitat von toko
ich hab nun folgende Prozedur:
Delphi-Quellcode:
procedure TfrmMain.sortXMLFile;
var
  xmlStyle: IXMLDOMDocument;
begin
  ...
  xmlStyle.load(FAppPath + 'data.xsl');
  xmlDoc.load(xmlDoc.transformNode(xmlStyle));
  cds := XMLDoc.documentElement.selectNodes('cd');
  ...
end;

Wenn du mit diesem Code eine Access-Violation bekommst, dann wundert mich das nicht. In der ersten Zeile lädst du den XSLT-Code. Der Aufruf der Methode transformNode() in der zweiten Zeile generiert den sortierten XML-Code, die load() Methode erwartet aber einen URL und scheitert. Als Ergebnis ist documentElement nicht instanziiert. Beim Aufruf der Methode selectNodes() knallt es dann.

In meiner ersten Antwort hatte ich dir eine Code-Zeile gegeben, deren Sinn dir vielleicht entgangen ist:

Delphi-Quellcode:
xmlDoc.loadXML(xmlDoc.transformNode(xmlStyle));
Wenn du aus einer Datei lädst, dann verwende load(), wenn du einen XML-String parsen möchtest, dann verwende loadXML().

Matthias hat dich darauf hingewiesen, dass die Transformation mit XSLT nicht direkt auf den Originaldaten durchgeführt wird. Du erhältst neuen XML-Code, den du natürlich wieder in der gleichen DOM Variable verarbeiten kannst. Beim Speichern wird dann immer deine zuletzt erstellte Sortierung gespeichert.

marabu

toko 2. Jun 2005 14:14

Re: Wie in XML-Datei sortieren?
 
OK, jetzt klappts. Danke, marabu, für deine Geduld. Ich probiere gleich noch mal die Sortierung nach verschiedenen Knoten.

Grüße

toko 2. Jun 2005 18:01

Re: Wie in XML-Datei sortieren?
 
Hallo,

eine kliztekleine Frage habe ich noch zur Sortierung. :oops: Ich wiederhole noch mal kurz, ob ich euch auch Verstanden habe:
Der Format-String(also diese
XML-Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <xsl:template match="/ | @* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()">
        <xsl:sort select="[color=#ff001f]%s[/color]"/>
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
XSL-Daten), der dem resourcenstring "fmtXSLdata" zugewiesen und der Formatierungsroutine "Format" übergeben werden soll, soll den Formatbezeichner "%s" enthalten (also so wie oben). Für s soll nun das Knotenattribut @id, @titel, @interpret, oder @genre gesetzt werden (unten ist in diesem Fall @titel eingetragen). Mit
Code:
  xmlDoc.loadXML(xmlDoc.transformNode(xmlStyle));
arbeite ich auf dem DomObjekt (die XSL-Daten mit dem übergebenen Knotenattribut). Im Ganzen dann
Delphi-Quellcode:
procedure TfrmMain.sortXMLFile;
var
  xmlStyle: IXMLDOMDocument;
  i : integer;
begin
  xmlStyle := CoDomDocument.Create;
  xmlStyle.async := false;
  {nächste Zeile entfällt da der resourcenstring die XSL-Daten enthalten soll.}
  //xmlStyle.load(FAppPath + 'dataSort.xsl');
  xmlStyle.loadXML(Format(fmtXSLdata, ['@titel']));
  xmlDoc.loadXML(xmlDoc.transformNode(xmlStyle));
  cds := XMLDoc.documentElement.selectNodes('cd');
  ...
end;
Wenn das soweit richtig ist, dann sieht das so
Delphi-Quellcode:
resourcestring
  fmtXSLdata = '<?xml version="1.0"?>' +
               '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >' +
                 '<xsl:template match="/ | @* | node()">' +
                   '<xsl:copy>' +
                     '<xsl:apply-templates select="@* | node()">' +
                       '<xsl:sort select="%s"/>' +
                     '</xsl:apply-templates>' +
                   '</xsl:copy>'+
                 '</xsl:template>'+
               '</xsl:stylesheet>';
aus. Muss ja, meine Daten werden auf jedenfall sortiert. Ohne jetzt undankbar zu wirken, kann man das im Code verschönern?

Grüße

marabu 2. Jun 2005 18:28

Re: Wie in XML-Datei sortieren?
 
Alles klappt?
Nur noch schöner soll es werden?
Du meinst den resourcestring verschönern?
Der ist doch schon hübsch!

Aber ich hätte noch ein paar Hinweise für dich, die du vielleicht jetzt noch nicht einordnen kannst, aber an die du dich zu gegebener Zeit erinnern solltest.

(1) titel ist bei dir Attribut nicht nur eines Element-Typs.
(2) Wenn du dir unsicher bist, ob du ein Attribut oder ein Element zum Speichern einer Information verwenden sollst, dann nimm das Element.
(3) Wenn du dir sicher bist, es müsste ein Attribut sein, dann prüfe dich selbst.

Sobald du das Gefühl hast, darüber reden zu müssen, tue es.

marabu

toko 2. Jun 2005 19:33

Re: Wie in XML-Datei sortieren?
 
OK, bis denn dann...


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:58 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