title: How to get the parent child relationship between connected mxgraph
body: <p>I'm trying to get simplified relationship between connected <code>mxgraph</code></p>
  
  <p><strong>Question:</strong>  I'm trying to get the simplified relationship, once the <strong>graph</strong> is drawn.</p>
  
  <p>i'm trying to get relationship between connected nodes in json.</p>
  
  <p><strong>Note:</strong> solution must work for every drawn state.</p>
  
  <p><strong>Here is codepen:</strong></p>
  
  <p><a href="https://codepen.io/eabangalore/pen/pmELpL" rel="noreferrer">https://codepen.io/eabangalore/pen/pmELpL</a></p>
  
  <p>i want to get the relationship from above code snippet.</p>
  
  <p><strong>Expected output (from drawn relationship):</strong></p>
  
  <pre><code>[
    {"id":0,"parent":"#","text":"A","child":[{"cid":1,"connectionText":"Bangalore"}]},
    {"id":1,"parent":0,"text":"B","child":[{"cid":2,"connectionText":""}]},
    {"id":2,"parent":1,"text":"C","child":[{"cid":null,"connectionText":""}]}
  ];
  </code></pre>
  
  <p><strong>Please refer codepen, as below snippet is not working.</strong></p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;!--
    Copyright (c) 2006-2013, JGraph Ltd
    
    Dynamic toolbar example for mxGraph. This example demonstrates changing the
    state of the toolbar at runtime.
  --&gt;
  &lt;html&gt;
  &lt;head&gt;
   &lt;title&gt;Toolbar example for mxGraph&lt;/title&gt;
  
   &lt;!-- Sets the basepath for the library if not in same directory --&gt;
    &lt;script type="text/javascript"&gt;
      mxBasePath = 'https://jgraph.github.io/mxgraph/javascript/src';
      
      function setGraphData(){
        var graphState ={"tagName":"mxGraphModel","children":[{"tagName":"root","children":[{"tagName":"mxCell","attributes":{"id":"0"}},{"tagName":"mxCell","attributes":{"id":"1","parent":"0"}},{"tagName":"mxCell","attributes":{"id":"2","value":"A","style":"","vertex":"1","parent":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"271.56251525878906","y":"82.44792175292969","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"3","value":"B","style":"","vertex":"1","parent":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"678.2291717529297","y":"106.89236450195312","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"4","value":"Bangalore","edge":"1","parent":"1","source":"2","target":"3"},"children":[{"tagName":"mxGeometry","attributes":{"relative":"1","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"5","value":"C","style":"","vertex":"1","parent":"1"},"children":[{"tagName":"mxGeometry","attributes":{"x":"1013.7847747802734","y":"83.55902862548828","width":"100","height":"40","as":"geometry"}}]},{"tagName":"mxCell","attributes":{"id":"6","edge":"1","parent":"1","source":"3","target":"5"},"children":[{"tagName":"mxGeometry","attributes":{"relative":"1","as":"geometry"}}]}]}]};
        
        localStorage.setItem('graphState',JSON.stringify(graphState));
      }
      
       function html2json(html){
    if(html.nodeType==3){
     return {
      "tagName":"#text",
      "content":html.textContent
     }
    }
    var element = {
     "tagName":html.tagName
    };
  
    if(html.getAttributeNames().length&gt;0){
     element.attributes = html.getAttributeNames().reduce(
      function(acc,at){acc[at]=html.getAttribute(at); return acc;},
      {}
     );
    }
  
    if(html.childNodes.length&gt;0){
     element.children = Array.from(html.childNodes)
      .filter(
       function(el){
        return el.nodeType!=3
        ||el.textContent.trim().length&gt;0
       })
      .map(function(el){return html2json(el);});
    }
    return element;
   }
  
   function json2html(json){
    var xmlDoc = document.implementation.createDocument(null, json.tagName);
  
    var addAttributes = function(jsonNode, node){
     if(jsonNode.attributes){
      Object.keys(jsonNode.attributes).map(
       function(name){
        node.setAttribute(name,jsonNode.attributes[name]);
       }
      );
     }
    }
  
    var addChildren = function(jsonNode,node){
     if(jsonNode.children){
      jsonNode.children.map(
       function(jsonChildNode){
        json2htmlNode(jsonChildNode,node);
       }
      );
     }
    }
  
    var json2htmlNode = function(jsonNode,parent){
     if(jsonNode.tagName=="#text"){
      return xmlDoc.createTextNode(jsonNode.content);
     }
  
     var node = xmlDoc.createElement(jsonNode.tagName);
  
     addAttributes(jsonNode,node);
     addChildren(jsonNode,node);
  
     parent.appendChild(node);
    }
  
    addAttributes(json,xmlDoc.firstElementChild);
    addChildren(json,xmlDoc.firstElementChild);
  
    return xmlDoc;
   }
    &lt;/script&gt;
  
    &lt;!-- Loads and initializes the library --&gt;
    &lt;script type="text/javascript" src="https://jgraph.github.io/mxgraph/javascript/src/js/mxClient.js"&gt;&lt;/script&gt;
  
   &lt;!-- Example code --&gt;
   &lt;script type="text/javascript"&gt;
    // Program starts here. Creates a sample graph in the
    // DOM node with the specified ID. This function is invoked
    // from the onLoad event handler of the document (see below).
    function main()
    {
        setGraphData();
     // Checks if browser is supported
     if (!mxClient.isBrowserSupported())
     {
      // Displays an error message if the browser is
      // not supported.
      mxUtils.error('Browser is not supported!', 200, false);
     }
     else
     {
      // Defines an icon for creating new connections in the connection handler.
      // This will automatically disable the highlighting of the source vertex.
      mxConnectionHandler.prototype.connectImage = new mxImage('images/connector.gif', 16, 16);
  
      // Creates the div for the toolbar
      var tbContainer = document.createElement('div');
      tbContainer.style.position = 'absolute';
      tbContainer.style.overflow = 'hidden';
      tbContainer.style.padding = '2px';
      tbContainer.style.left = '0px';
      tbContainer.style.top = '0px';
      tbContainer.style.width = '24px';
      tbContainer.style.bottom = '0px';
      
      document.body.appendChild(tbContainer);
     
      // Creates new toolbar without event processing
      var toolbar = new mxToolbar(tbContainer);
      toolbar.enabled = false
      
      // Creates the div for the graph
      var container = document.createElement('div');
      container.style.position = 'absolute';
      container.style.overflow = 'hidden';
      container.style.left = '24px';
      container.style.top = '0px';
      container.style.right = '0px';
      container.style.bottom = '0px';
      container.style.background = 'url("editors/images/grid.gif")';
  
      document.body.appendChild(container);
      
      // Workaround for Internet Explorer ignoring certain styles
      if (mxClient.IS_QUIRKS)
      {
       document.body.style.overflow = 'hidden';
       new mxDivResizer(tbContainer);
       new mxDivResizer(container);
      }
   
      // Creates the model and the graph inside the container
      // using the fastest rendering available on the browser
      var model = new mxGraphModel();
      var graph = new mxGraph(container, model);
  
      // Enables new connections in the graph
      graph.setConnectable(true);
      graph.setMultigraph(false);
  
      // Stops editing on enter or escape keypress
      var keyHandler = new mxKeyHandler(graph);
      var rubberband = new mxRubberband(graph);
      
      var addVertex = function(icon, w, h, style)
      {
       var vertex = new mxCell(null, new mxGeometry(0, 0, w, h), style);
       vertex.setVertex(true);
      
       var img = addToolbarItem(graph, toolbar, vertex, icon);
       img.enabled = true;
       
       graph.getSelectionModel().addListener(mxEvent.CHANGE, function()
       {
        var tmp = graph.isSelectionEmpty();
        mxUtils.setOpacity(img, (tmp) ? 100 : 20);
        img.enabled = tmp;
       });
      };
      
      addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rectangle.gif', 100, 40, '');
      addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rounded.gif', 100, 40, 'shape=rounded');
      addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/ellipse.gif', 40, 40, 'shape=ellipse');
      addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/rhombus.gif', 40, 40, 'shape=rhombus');
      addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/triangle.gif', 40, 40, 'shape=triangle');
      addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/cylinder.gif', 40, 40, 'shape=cylinder');
      addVertex('https://jgraph.github.io/mxgraph/javascript/examples/editors/images/actor.gif', 30, 40, 'shape=actor');
          
          
             // read state on load 
      if(window.localStorage.graphState){ 
       var doc = json2html(JSON.parse(localStorage.graphState)); 
       var dec = new mxCodec(doc);
       dec.decode(doc.documentElement, graph.getModel());
      }
  
      // save state on change
      graph.getModel().addListener('change',function(){
        var codec = new mxCodec();  
        window.localStorage.graphState = JSON.stringify(html2json(codec.encode(
         graph.getModel()
        )));
      });
     }
    }
  
    function addToolbarItem(graph, toolbar, prototype, image)
    {
     // Function that is executed when the image is dropped on
     // the graph. The cell argument points to the cell under
     // the mousepointer if there is one.
     var funct = function(graph, evt, cell, x, y)
     {
      graph.stopEditing(false);
  
      var vertex = graph.getModel().cloneCell(prototype);
      vertex.geometry.x = x;
      vertex.geometry.y = y;
       
      graph.addCell(vertex);
      graph.setSelectionCell(vertex);
     }
     
     // Creates the image which is used as the drag icon (preview)
     var img = toolbar.addMode(null, image, function(evt, cell)
     {
      var pt = this.graph.getPointForEvent(evt);
      funct(graph, evt, cell, pt.x, pt.y);
     });
     
     // Disables dragging if element is disabled. This is a workaround
     // for wrong event order in IE. Following is a dummy listener that
     // is invoked as the last listener in IE.
     mxEvent.addListener(img, 'mousedown', function(evt)
     {
      // do nothing
     });
     
     // This listener is always called first before any other listener
     // in all browsers.
     mxEvent.addListener(img, 'mousedown', function(evt)
     {
      if (img.enabled == false)
      {
       mxEvent.consume(evt);
      }
     });
        
     mxUtils.makeDraggable(img, graph, funct);
     
     return img;
    }
  
   &lt;/script&gt;
  &lt;/head&gt;
  
  &lt;!-- Calls the main function after the page has loaded. Container is dynamically created. --&gt;
  &lt;body onload="main();" &gt;
  &lt;/body&gt;
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>please help me thanks in advance!!! </p>