Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   XML (https://www.delphipraxis.net/46-xml/)
-   -   Delphi XML "String Wurst" formatieren (https://www.delphipraxis.net/137757-xml-string-wurst-formatieren.html)

t4rI 28. Jul 2009 09:07


XML "String Wurst" formatieren
 
Hi liebe Community,
ich habe eine kleines Problem.
Ich bekomme regelmäßig XML Dateien geschickt, die keine Formatierung enthalten und deshalb aussehen wie eine "String Wurst".
Ich denke jeder weiß was ich meine :lol: .
Nun möchte ich ein Programm machen, welches mir diese Wurst Formatier.
Bisher kam ich nur auf die Idee das ">" Zeichen durch einen Zeilen Umbruch zu ersetzen.
Doch nun stehen alle Nodes untereinander und es ist trotzdem kaum zu lesen!
Hat jemand vielleicht eine Lösung für dieses Problem oder vielleicht kann mir jemand einen Denkanstoß geben ....
Mir fällt gerade wirklich nichts ein :wall:
Naja... ich hoffe mal auf auch, weil :dp:.
Danke schon einmal im Vorraus ....
Gruß
t4rI

jfheins 28. Jul 2009 09:11

Re: XML "String Wurst" formatieren
 
Parsen und mit der gewünschten Formatierung wieder ausgeben wäre eine Möglichkeit - das mit dem Suchen und ersetzen ist wahrscheinlich nicht die beste Lösung.

xml-Parser solltest du zu genüge finden, die können dir eine Baumstruktur aufbauen. Danach kannste den Baum wieder ausgeben, mit entsprechenden Leerzeichen/Tabs je nach Tiefe ;)

Oder (etwas Q&D) du gehst deinen String durch und suchst nach einem < falls danach ein / kommt, merken. Danach suchst du nach einem > falls am Anfang ein / war: Ebene um 1 veringern. Falls am ende ein / war: Ebene nicht verändern. ansonsten: Ebene um 1 erhöhen. Dann den Tag an dieser Stelle (Ebene=>Leerzeichen) ausgeben, und nen Zeilenumruch einfügen. Das was nach dem Tag kommt ausgeben, Zeilenumbruch einfügen, und von vorne anfangen ;)

Stevie 28. Jul 2009 09:26

Re: XML "String Wurst" formatieren
 
Mit Bordmitteln:

Delphi-Quellcode:
uses
  XMLDoc, XMLIntf;

procedure FormatXmlFile(const ASourceFileName, ATargetFileName: string);
var
  LXmlDoc: TXMLDocument;
begin
  LXmlDoc := TXMLDocument.Create(ASourceFileName);
  LXmlDoc.Active := True;
  LXmlDoc.Options := LXmlDoc.Options + [doNodeAutoIndent];
  LXmlDoc.SaveToFile(ATargetFileName);
  LXmlDoc.Active := False;
  LXmlDoc.Free;
end;

t4rI 28. Jul 2009 09:47

Re: XML "String Wurst" formatieren
 
Hallo,
erstmal danke für die schnelle Hilfe !

Der Quellcode von Stevie ändert die Formation meiner XML garnicht.
:/
Ich werd mal schauen ob ich einen Parser bauen kann ...

gruß
t4rI

himitsu 28. Jul 2009 09:57

Re: XML "String Wurst" formatieren
 
Zitat:

Zitat von t4rI
Der Quellcode von Stevie ändert die Formation meiner XML garnicht.

bei MSDML mußte brindt das ändern der Optionen nur etwas, bei danach neu erstellten Nodes ... alte bleiben unberühert ... da mußte man irgendwie den "Neuaufbau" manuell anstoßen, aber mir fällt grad nicht ein wie (dürfte aber in ein paar DP-Threads zu finden sein)
Zitat:

Zitat von t4rI
Ich werd mal schauen ob ich einen Parser bauen kann ...

na dann viel Spaß ... aber nimm dann lieber einen Fertigen ... ist nicht so leicht, wie man denkt :stupid:


[add]
Hier im Forum suchendoNodeAutoIndent > http://www.delphipraxis.net/internal...nodeautoindent

t4rI 28. Jul 2009 10:12

Re: XML "String Wurst" formatieren
 
Ja hab ich jetzt auch beim "ersten Reinschnuppern" gemerkt!. :wiejetzt:
Vielleicht sollte ich doch lieber Probieren den Neuaufbau manuell anzustoßen....
Hat jemand vielleicht dafür eine Idee :gruebel: ???

Gruß
t4rI

nahpets 28. Jul 2009 10:45

Re: XML "String Wurst" formatieren
 
Hallo,

wie sehen denn Deine XML-Dateien inhaltlich aus?
Nur in der Form Öffnen- und Schließentag mit Einträgen dazwischen oder auch mit CDATA?
Wenn kein CDATA in der XML-Datei vorkommt, kannst Du meiner Meinung nach zuerst jedes < durch einen Zeilenumbruch ersetzen und anschließend aus jedem Zeilenumbruch + </ ein </ machen.
Nun musst Du "nurnoch" aus jedem ></ ein > + Zeilenumbruch + </ machen.
Danach stehen linksbündig alle Öffnentags untereinander.
Anschließend wird ab dem zweiten < ein zusätzliches Leerzeichen eingefügt und bei jedem </ ein Leerzeichen weniger.

Im Quelltext könnte das (ungetestet) etwa so aussehen:
Delphi-Quellcode:
var
  xml : TStringList;
  leer : String;
  i   : Integer;
begin
  leer := '';
  xml := TStringList.Create;
  xml.LoadFromFile('XML-Datei.xml');
  xml.Text := AnsiReplaceText(xml.Text,'<',#13#10 + '<');
  xml.Text := AnsiReplaceText(xml.Text,#13#10 + '</','</');
  xml.Text := AnsiReplaceText(xml.Text,'></','>' + #13#10 + '</');
  for i := 1 to xml.Count - 1 do begin
    if Copy(xml[i],1,2) = '</' then begin
      leer := copy(leer,1,Length(leer) - 1);
    end
    if Copy(xml[i],1,1) = '<' then begin
      leer := leer + ' ';
    end;
    xml[i] := leer + xml[i];
  end;
  while Trim(xml[0]) = '' do xml.Delete(0);
  xml.SaveToFile('XML-Datei.neu.xml');
  xml.Free;
end;
Nur mal eben so hingedattelt, über Eleganz und Performanz wollen wir hier mal lieber nicht reden.

t4rI 28. Jul 2009 10:58

Re: XML "String Wurst" formatieren
 
hi naphets,

das könnte klappen habe es jetzt noch nicht ausprobiert, da ich schon eine andere Lösung gefunden habe!

Delphi-Quellcode:
procedure TForm1.Beautify(const XML: IXMLDOMDocument;
  const IndentString: WideString = #9);

  procedure InsertFormattingNode(const Node: IXMLDOMNode;
    const Len, Index: Integer; Break: Boolean = True);
  var
    I: Integer;
    IndentStr: WideString;
  begin
    for I := 1 to Len do begin
      IndentStr := IndentStr + IndentString;
    end;
    if Break then
      IndentStr := SLineBreak + IndentStr;

     InsertTextNode(Node, IndentStr, Index);
  end;

          procedure ProcessList(const Node: IXMLDOMNode);
          var
            I: Integer;
            Nesting: Integer;
          begin
            if not Assigned(Node) then
              Exit;
            I := 0;
            Nesting := GetNesting(Node);
            while I < Node.childNodes.length do
            begin
              if (Node.childNodes[I].nodeType = NODE_ATTRIBUTE) or (Node.childNodes[I].nodeName = '#text') then
              begin
                Inc(I);
                Continue;
              end;

              if I = 0 then
                InsertFormattingNode(Node, Nesting + 1, I)
              else
                InsertFormattingNode(Node, 1, I, False);

              Inc(I, 2);

              InsertFormattingNode(Node, Nesting, I);
              Inc(I);
            end;

            for I := 0 to Node.childNodes.length - 1 do
              ProcessList(Node.childNodes[I]);
          end;

begin
  ProcessList(XML.documentElement);
end;

function TForm1.GetNesting(const Node: IXMLDOMNode): Integer;
var
  Parent: IXMLDOMNode;
begin
  Result := 0;
  Parent := Node.parentNode;
  while Assigned(Parent) and (Parent.nodeType <> NODE_DOCUMENT) do begin
    Parent := Parent.parentNode;
    Inc(Result);
  end;
end;

function TForm1.InsertTextNode(const Parent: IXMLDOMNode;
  const Content: WideString; const Index: Integer = -1): IXMLDOMNode;
var
    XML: IXMLDomDocument;
begin
    if Assigned(Parent) then begin
        XML := Parent.ownerDocument;
        if Assigned(XML) then begin
            Result := XML.createTextNode(Content);
            if Index = -1 then begin
                Parent.appendChild(Result)
            end
            else
                Parent.insertBefore(Result, Parent.childNodes[Index]);
        end
        else
          Result := nil;
      end
      else
        Result := nil;
end;
Das habe ich in DP gefunden und es funktioniert 1a !!!! :bouncing4: :bounce1: :bounce1: :bouncing4: :bounce1: :bouncing4: :bounce1:
Vielen Dank trotzdem an alle!
MFG
t4rI

mjustin 28. Jul 2009 11:16

Re: XML "String Wurst" formatieren
 
Mit Bordmitteln (uses xmldoc):

Delphi-Quellcode:
FormatiertesXML := FormatXMLData(XMLString);
Viele Grüße,

Luckie 28. Jul 2009 11:29

Re: XML "String Wurst" formatieren
 
Mal was anderes. Wozu der Aufwand? XML-dateien sind eiegntlich nicht dafür gedacht von Menschen gelesen und bearbeitet zu werden. Sie sind ursprünglich dazu gedacht gewesen, um daten zwischen Programmen austauschen zu können. Und dem Programm ist es egal, wie die XML-Datei formatiert ist.

himitsu 28. Jul 2009 11:34

Re: XML "String Wurst" formatieren
 
hätte auch noch via Hier im Forum suchenhimXML sowas bieten können ... via Standardeinstellung sieht es ja so aus diese Formatierungen werden beim Auslesen ignoriert
Delphi-Quellcode:
xml: TXMLFile;

xml := TXMLFile.Create;
xml.LoadFromFile(...);
xml.SaveToFile(...);
xml.Free;
aber hierzu
Delphi-Quellcode:
xml.Text := AnsiReplaceText(xml.Text,'<',#13#10 + '<');
xml.Text := AnsiReplaceText(xml.Text,#13#10 + '</','</');
xml.Text := AnsiReplaceText(xml.Text,'></','>' + #13#10 + '</');
die Zeile 1 entspricht der Zeile 2, also werden bei </ 2 Leerzeilen davor eingefügt

und die dritte Zeile macht nie was, da Zeile 1&2 ebenfalls diesem Muster entsprechen, demnach schon Umbrüche eingefügt sind und es keine ></ mehr gibt.

t4rI 28. Jul 2009 12:58

Re: XML "String Wurst" formatieren
 
@ Luckie
Ja du hast schon Recht mit dem was du sagst/schreibst!
Doch ich muss die Dateien auch so auslesen können, da ich auch gerade ein Programm schreibe um XML's zu erstellen und ich schauen möchte ob das
Programm alles Richtig macht!
Das ist ein wenig umständlich wenn die Formatierung nicht stimmt. :drunken:

Aber nochmal vielen Dank für die schnelle Hilfe!!!
Gruß
t4rI

Bernhard Geyer 28. Jul 2009 13:00

Re: XML "String Wurst" formatieren
 
Zitat:

Zitat von t4rI
Doch ich muss die Dateien auch so auslesen können, da ich auch gerade ein Programm schreibe um XML's zu erstellen und ich schauen möchte ob das
Programm alles Richtig macht!
Das ist ein wenig umständlich wenn die Formatierung nicht stimmt. :drunken:

Dann zie die Datei doch auf den IE oder Firefox. Der wird dir schon melden ob das XML passt oder nicht.

Kalfany 28. Jul 2009 13:06

Re: XML "String Wurst" formatieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also wenns nicht gleich ein eigenes Programm sein soll, Notepad++ kann das auch. Dazu müssen nur die Notepad++ Erweiterungen installiert sein.

TextFX -> TextFX HTML Tidy -> Tidy: Reindent XML


@Luckie
Manchmal möchte man aber etwas an der Datei etwas von Hand ändern, du hast sicher auch schon mal die Config-Datei von einem Programm angepasst (egal ob ini oder xml) ... gäb jetzt viele Gründe ...

auch sind solche XML-Dateien mehr als unschön (und die paar Whitespaces machen eine XML-Datei auch nicht mehr fett :D ) denn manche Parser haben ein Problem wenn eine 5MB XML-Datei aus nur einer Zeile besteht.

t4rI 28. Jul 2009 13:12

Re: XML "String Wurst" formatieren
 
@ Bernhard

Genau das was Kalfany geschrieben hat war das Problem was ich hatte!
Natürlich kann ich mit IE oder Firefox die XML öffnen, die mir dann auch schön als Tree wiedergegeben wird, doch kann ich diese dann auch bearbeiten ? :gruebel: ^^

Gruß
t4rI

mjustin 28. Jul 2009 14:10

Re: XML "String Wurst" formatieren
 
Zitat:

Zitat von Luckie
Mal was anderes. Wozu der Aufwand? XML-dateien sind eiegntlich nicht dafür gedacht von Menschen gelesen und bearbeitet zu werden. Sie sind ursprünglich dazu gedacht gewesen, um daten zwischen Programmen austauschen zu können. Und dem Programm ist es egal, wie die XML-Datei formatiert ist.

Die XML Spezifikation läßt eigentlich eher den Schluss zu, dass XML auch gerade die nichtmaschinelle Leserschaft anspricht: ein XML-Dokument besteht aus Textzeichen, im einfachsten Fall ASCII, und ist damit menschenlesbar – Binärdaten enthält es per Definition nicht.

Viele Konfigurationsdateien für Anwendungen werden im XML Format bereitgestellt, was die Validierung erleichtert, aber editiert werden sie aber nicht mit darauf zugeschnittenen Editoren. Das ist eher die Ausnahme und nur bei sehr weit verbreiteten Formaten gängig, wie z.B. Deploymentdeskriptoren oder Loggerkonfigurationsdateien.

Luckie 28. Jul 2009 14:41

Re: XML "String Wurst" formatieren
 
Zitat:

Zitat von mjustin
aber editiert werden sie aber nicht mit darauf zugeschnittenen Editoren.

Nein, aber mit dem Programm selber, was sie erstellt bzw. ausliest. Wenn ein Programm seine Konfiguration in XML-Dateien speichert, dann ist das Programm selber der Editor und Leser/Auswerter. Und wenn ich gucken will, ob das so stimmt, was mein programm schreibt, kann ich die Datei im Browser öffnen.

p80286 28. Jul 2009 16:01

Re: XML "String Wurst" formatieren
 
Zitat:

Zitat von Luckie
Nein, aber mit dem Programm selber, was sie erstellt bzw. ausliest. Wenn ein Programm seine Konfiguration in XML-Dateien speichert, dann ist das Programm selber der Editor und Leser/Auswerter. Und wenn ich gucken will, ob das so stimmt, was mein programm schreibt, kann ich die Datei im Browser öffnen.

Naja nicht ganz, wenn z.B. die DTD weit und breit nicht verfügbar ist, dan haben Browser schon ein Problem.
Zitat:

Zitat von Luckie
Sie sind ursprünglich dazu gedacht gewesen, um daten zwischen Programmen austauschen zu können.

Und da ist's kein Fehler in die XML-Datei reinschauen zu können.

Gruß
K-H

t4rI 29. Jul 2009 08:32

Re: XML "String Wurst" formatieren
 
Eine weitere Frage wäre ....
wie bekommt man die "String Wurst" wieder hin um es für andere wieder schwer leserlich zu machen ^^
ich denke da setzt ich mich jetzt mal dran :D

Gruß
t4rI

nahpets 29. Jul 2009 09:19

Re: XML "String Wurst" formatieren
 
Zitat:

Zitat von himitsu
Delphi-Quellcode:
xml.Text := AnsiReplaceText(xml.Text,'<',#13#10 + '<');
xml.Text := AnsiReplaceText(xml.Text,#13#10 + '</','</');
xml.Text := AnsiReplaceText(xml.Text,'></','>' + #13#10 + '</');
die Zeile 1 entspricht der Zeile 2, also werden bei </ 2 Leerzeilen davor eingefügt

und die dritte Zeile macht nie was, da Zeile 1&2 ebenfalls diesem Muster entsprechen, demnach schon Umbrüche eingefügt sind und es keine ></ mehr gibt.

Wieso:
Die erste Zeile macht aus < Zeilenumbruch plus <.
Die zweite Zeile macht aus Zeilenumbruch plus </ ein </, entfernt also einen von </ gefolgten Zeilenumbruch.
Danach kann es daher wieder ein ></ geben, was in der dritten Zeile zu einem > plus Zeilenumbruch plus </ wird.

Zitat:

Zitat von t4rI
Eine weitere Frage wäre ....
wie bekommt man die "String Wurst" wieder hin um es für andere wieder schwer leserlich zu machen ^^

Schmeiß doch alle Zeilenumbrüche raus:
Delphi-Quellcode:
xml.Text := AnsiReplaceText(xml.Text,#13#10,'');
@Luckie
Bei fremden XML-Dateien finde ich es zuweilen durchaus sinnvoll und angenehm, sie mal im Editor richtig lesen zu können, zumal, wenn ich fehlerhafte XML-Dateien bekomme und sie händisch oder per Programm korrigieren muss.
Im Browser bekomme ich nur korrekte Dateien geöffnet, bei fehlerhaften wird ein Hinweis auf die Fehlerstelle gegeben, aber korrigieren muss man die Fehler dann in der "Wurst".

Bernhard Geyer 29. Jul 2009 09:32

Re: XML "String Wurst" formatieren
 
Zitat:

Zitat von t4rI
... doch kann ich diese dann auch bearbeiten ? :gruebel: ^^

Ich verwende seit einiger Zeit XML Notepad

t4rI 29. Jul 2009 09:43

Re: XML "String Wurst" formatieren
 
@ naphets
Ja das dacht ich mit auch schon nur er kennt kein AnsiReplaceText! :cry:

Gruß
t4rI

t4rI 29. Jul 2009 09:51

Re: XML "String Wurst" formatieren
 
bin gerade dabei etwas auszuprobieren
und zwar möchte ich einfach alles löschen was zwischen "/>" und "<" steht doch ich weiß nicht wie ich die zeichen zwischen den zeichen ansprechen soll!
^^ wie ihr wahrscheinlich schon alle gemerkt habt bin ich blutiger anfänger und programmiere jetzt erst seid 1nem monat :oops:
Gruß
t4rI

nahpets 29. Jul 2009 10:10

Re: XML "String Wurst" formatieren
 
Hallo,

für AnsiReplaceText musst Du StrUtils in die Usesliste aufnehmen.

Um die von Dir eingefügten Leerzeichen zur Formatierung zu entfernen, könntest Du folgendermaßen vorgehen:
Delphi-Quellcode:
Uses
  ...
  StrUtils;

var
  xml : TStringList;
  i   : Integer;
begin
  xml := TStringList.Create;
  xml.LoadFromFile('XML-Datei.xml');
  for i := 0 to xml.Count - 1 do xml[i] := Trim(xml[i]);
  xml.Text := AnsiReplaceText(xml.text,#13#10,'');
  xml.SaveToFile('XML-Datei.neu.xml');
  xml.Free;
end;

t4rI 29. Jul 2009 10:42

Re: XML "String Wurst" formatieren
 
Danke !!!! klappt super!!!
:dp:
Gruß
t4rI


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