Delphi-PRAXiS
Seite 1 von 3  1 23      

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.


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:27 Uhr.
Seite 1 von 3  1 23      

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