Daten strukturiert anzeigen mit DOT

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Kiffi
Beiträge: 10621
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Daten strukturiert anzeigen mit DOT

Beitrag von Kiffi »

Hallo,

wer Daten in einer strukturierten Form als Grafik anzeigen lassen will, der kann sich ja mal DOT anschauen.
Wikipedia hat geschrieben:DOT ist eine einfach gehaltene, aber mächtige Beschreibungssprache für die visuelle Darstellung von Graphen. Mit DOT lässt sich die Struktur eines gerichteten oder ungerichteten Graphen beschreiben. Außerdem besitzt DOT auch Sprachelemente, um die Visualisierung eines Graphen zu steuern. Zum Beispiel lassen sich Form und Farbe der Knoten und der Kanten festlegen. [...]
(Quelle: https://de.wikipedia.org/wiki/DOT_(GraphViz))
Hier ein kleines Beispiel, wie sich eine XML-Struktur in DOT konvertieren und als Grafik anzeigen lässt:

Code: Alles auswählen

EnableExplicit

; http://www.graphviz.org/

; https://de.wikipedia.org/wiki/DOT_(GraphViz)

Procedure.s ReadXmlStructure(Node)
  
  Static ReturnValue.s
  
  Protected ChildNode
  Protected ChildXMLNodeName.s
  Protected ParentXMLNodeName.s
  
  ChildNode = ChildXMLNode(Node)
  
  While ChildNode <> 0
    
    If XMLNodeType(ParentXMLNode(ChildNode)) = #PB_XML_Normal 
      ParentXMLNodeName = GetXMLNodeName(ParentXMLNode(ChildNode))
    EndIf
    
    If XMLNodeType(ChildNode) = #PB_XML_Normal 
      ChildXMLNodeName = GetXMLNodeName(ChildNode)
    EndIf
    
    If ParentXMLNodeName <> "" And ChildXMLNodeName <> ""
      ReturnValue + ParentXMLNodeName + " -> " + ChildXMLNodeName + ";" + #CRLF$
    EndIf
    
    If XMLChildCount(ChildNode)
      ReadXmlStructure(ChildNode)
    EndIf
    
    ChildNode = NextXMLNode(ChildNode)
    
  Wend
  
  ProcedureReturn ReturnValue
  
EndProcedure

InitNetwork()

Define XmlStructure.s
Define TempXmlFileName.s
Define TempDotFileName.s
Define TempPngFileName.s
Define DotExe.s
Define FF, oXML

TempXmlFileName = GetTemporaryDirectory() + "dot.xml"

If ReceiveHTTPFile("http://www.w3schools.com/xml/cd_catalog.xml", TempXmlFileName)
  
  oXML = LoadXML(#PB_Any, TempXmlFileName)
  
  If oXML 
    
    If XMLStatus(oXML) = #PB_XML_Success
      
      XmlStructure = ReadXmlStructure(RootXMLNode(oXML))
      
      XmlStructure = RemoveString(XmlStructure, ".") ; DOT mag keine Punkte als Bezeichner?
      
      XmlStructure = "strict digraph xml {" + #CRLF$ + "graph [rankdir=LR];" + XmlStructure + "}"
      
      TempDotFileName = GetTemporaryDirectory() + "dot.dot"
      TempPngFileName = GetTemporaryDirectory() + "dot.png"
      
      FF = CreateFile(#PB_Any, TempDotFileName)
      
      If FF
        
        WriteString(FF, XmlStructure)
        CloseFile(FF)
        
        TempDotFileName = Chr(34) + TempDotFileName + Chr(34)
        TempPngFileName = Chr(34) + TempPngFileName + Chr(34)
        
        DotExe = "C:\Program Files (x86)\Graphviz\bin\dot.exe" ; Anpassen!
        
        If RunProgram(DotExe, "-Tpng " + TempDotFileName + " -o " + TempPngFileName, "", #PB_Program_Wait | #PB_Program_Hide)
          
          RunProgram(TempPngFileName)
          
        Else
          
          Debug "!RunProgram()"
          
        EndIf
        
      Else
        
        Debug "!CreateFile()"
        
      EndIf
      
    Else
      
      Debug "!XMLStatus()"
      Debug XMLError(oXML)
      
    EndIf
    
    FreeXML(oXML)
    
  Else
    
    Debug "!oXML"
    
  EndIf
  
Else
  
  Debug "!ReceiveHTTPFile()"
  
EndIf
[/size]

Bevor Ihr den Code laufen lasst: Graphviz unter http://www.graphviz.org/ herunterladen und installieren. dot.exe im bin-Ordner lokalisieren und den Pfad in DotExe vermerken.

So wird aus folgendem XML:

Code: Alles auswählen

<CATALOG>
 <CD>
  <TITLE>Empire Burlesque</TITLE>
  <ARTIST>Bob Dylan</ARTIST>
  <COUNTRY>USA</COUNTRY>
  <COMPANY>Columbia</COMPANY>
  <PRICE>10.90</PRICE>
  <YEAR>1985</YEAR>
 </CD>
 <CD>
  <TITLE>Hide your heart</TITLE>
  <ARTIST>Bonnie Tyler</ARTIST>
  <COUNTRY>UK</COUNTRY>
  <COMPANY>CBS Records</COMPANY>
  <PRICE>9.90</PRICE>
  <YEAR>1988</YEAR>
 </CD>
 [...]
[/size]

dieses PNG:

Bild

Viel Spaß beim Experimentieren mit DOT! :-)

// Edit: defekten Graphviz-Link korrigiert.
Zuletzt geändert von Kiffi am 09.10.2015 12:08, insgesamt 1-mal geändert.
Hygge
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Daten strukturiert anzeigen mit DOT

Beitrag von NicTheQuick »

Funktioniert übrigens auch unter Linux, wenn man als DotExe einfach "dot" angibt. Allerdings öffnet sich das PNG-Bild nicht automatisch mit 'RunProgram()'. Da muss man zu "/tmp/dot.png" wechseln und es selbst öffnen. Und vorher muss man natürlich das Paket "graphviz" installieren.
Bild
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Daten strukturiert anzeigen mit DOT

Beitrag von Nino »

Sehr cool! 8)
Ganz, ganz vielen Dank für diesen Trick :!:
Funktioniert hier prima auf Anhieb (Windows 10).
Kiffi hat geschrieben:Viel Spaß beim Experimentieren mit DOT! :-)
Die Möglichkeiten sind ja unbegrenzt ...
Benutzeravatar
Kiffi
Beiträge: 10621
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Daten strukturiert anzeigen mit DOT

Beitrag von Kiffi »

hier nochmal ein anderes Beispiel, welches die Google-Api verwendet. Hierfür muss Graphviz nicht lokal installiert sein.

(funktioniert wg. ReceiveHTTPMemory() nur mit der neuen PB-Version 5.4)

Code: Alles auswählen

EnableExplicit
InitNetwork()
UsePNGImageDecoder()

Procedure GetChartImage(ChartData.s)
  
  Protected *Buffer
  Protected Image
  
  ChartData = URLEncoder(ChartData)
  
  *Buffer = ReceiveHTTPMemory("https://chart.googleapis.com/chart?" + ChartData)
  If *Buffer
    Image = CatchImage(#PB_Any, *Buffer)
    FreeMemory(*Buffer)
  Else
    Debug "Failed"
  EndIf
  
  ProcedureReturn Image
  
EndProcedure

; http://www.tonyballantyne.com/graphs.html
Define DOT.s = "digraph hierarchy {" + 
               "  nodesep=1.0" + 
               "  node [color=Red,fontname=Courier,shape=box]" + 
               "  edge [color=Blue, style=dashed]" + 
               "  Headteacher->{Deputy1 Deputy2 BusinessManager}" + 
               "  Deputy1->{Teacher1 Teacher2}" + 
               "  BusinessManager->ITManager" + 
               "  {rank=same;ITManager Teacher1 Teacher2}" + 
               "}"

Define ChartImage = GetChartImage("cht=gv&chl=" + DOT)

If IsImage(ChartImage)
  If OpenWindow(0, #PB_Ignore, #PB_Ignore, 800, 800, "ImageGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ImageGadget(0, 0, 0, ImageWidth(ChartImage), ImageHeight(ChartImage), ImageID(ChartImage))
    ResizeWindow(0, #PB_Ignore, #PB_Ignore,ImageWidth(ChartImage), ImageHeight(ChartImage))
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
  EndIf
EndIf
(der Einfachheit halber habe ich es per GET-Parameter gelöst; umfangreichere Daten müssten via POST gesendet werden)

Weitere Google-Chart-Infos hierzu: https://developers.google.com/chart/ima ... y/graphviz

Grüße ... Peter

// Edit: Fehlende Deklaration ergänzt
Zuletzt geändert von Kiffi am 09.10.2015 14:49, insgesamt 1-mal geändert.
Hygge
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Daten strukturiert anzeigen mit DOT

Beitrag von RSBasic »

:allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Nino
Beiträge: 1300
Registriert: 13.05.2010 09:26
Wohnort: Berlin

Re: Daten strukturiert anzeigen mit DOT

Beitrag von Nino »

Kiffi hat geschrieben:hier nochmal ein anderes Beispiel, welches die Google-Api verwendet. Hierfür muss Graphviz nicht lokal installiert sein.
Auch dafür herzlichen Dank!
Benutzeravatar
Rings
Beiträge: 971
Registriert: 29.08.2004 08:48

Re: Daten strukturiert anzeigen mit DOT

Beitrag von Rings »

Auch wenn es schon länger her ist,

Herzlichen Dank an Kiffi für die 2 Beispiele.


Kann ich super nutzen hier.
Rings hat geschrieben:ziert sich nich beim zitieren
Antworten