Seite 1 von 1

Daten strukturiert anzeigen mit DOT

Verfasst: 08.10.2015 23:55
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.

Re: Daten strukturiert anzeigen mit DOT

Verfasst: 09.10.2015 10:09
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.

Re: Daten strukturiert anzeigen mit DOT

Verfasst: 09.10.2015 11:31
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 ...

Re: Daten strukturiert anzeigen mit DOT

Verfasst: 09.10.2015 14:10
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

Re: Daten strukturiert anzeigen mit DOT

Verfasst: 09.10.2015 14:13
von RSBasic
:allright:

Re: Daten strukturiert anzeigen mit DOT

Verfasst: 11.10.2015 12:26
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!

Re: Daten strukturiert anzeigen mit DOT

Verfasst: 21.07.2016 16:42
von Rings
Auch wenn es schon länger her ist,

Herzlichen Dank an Kiffi für die 2 Beispiele.


Kann ich super nutzen hier.