3

TLDR;

When building a force directed graph based on multiple XML datasources, all the nodes appear stacked in the top left corner of the graph. Given there are no errors showing in console and all the nodes and links are correctly loaded afaik, what D3.js incorrect configuration could cause this behaviour?

Situation

Based on Mike Bostock's example of a Force-Directed Layout from XML https://bl.ocks.org/mbostock/1080941, I am loading multiple XML files using d3.queue and I am trying to display the force graph. When I am using one XML file the graph shows 1 node. However, when I am using multiple XML's the graph shows all the nodes in the top left corner. The console does not show any errors and all the required nodes and links objects are correctly loaded afaik.

Given

Edit: I have reduced code to a bare minimum to reproduce the problem. Four files are needed. Two small xml files, one json file and the html file.

FileList.json

[
"City.hbm.xml",
"Country.hbm.xml"
]

City.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="nl.sander.mieras.localhost.sakila.City" table="city" catalog="sakila">
        <!-- removed for readability -->
    </class>
</hibernate-mapping>

Country.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="nl.sander.mieras.localhost.sakila.Country" table="country" catalog="sakila">
        <!-- removed for readability -->
    </class>
</hibernate-mapping>

And the signifcantly reduced html file:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
    .link {
        stroke: #ccc;
    }

    .node {
        fill: #000;
        stroke: #fff;
        stroke-width: 2px;
    }
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/d3-queue.v2.min.js"></script>
<script>
    var width = 960,
            height = 500;

    var radius = d3.scale.sqrt()
            .domain([0, 20000])
            .range([0, 20]);

    var force = d3.layout.force()
            .charge(-240)
            .linkDistance(40)
            .size([width, height]);

    var svg = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", height);

    d3.json("FileList.json", function (error, fileArray) {
        var q = d3_queue.queue();
        fileArray.forEach(function (d) {
            q = q.defer(d3.xml, d);
        });
        q.await(analyze);
    });

    function analyze(error) {
        if (error) {
            console.log(error);
        }
        // skip 0 it's error variable
        for (i = 1; i < arguments.length; i++) {
            var xml = arguments[i];
            var nodes = [];
            var label = d3.select(xml).select("class").attr("table").charAt(0).toUpperCase() + d3.select(xml).select("class").attr("table").slice(1);
            nodes.push({
                "id": nodes.length,
                "label": label
            });

            console.log(nodes);
            node = nodes[0];
            node.x = width / 2;
            node.y = height / 2;

            force
                    .nodes(nodes)
                    .start();

            var node = svg.selectAll(".node")
                    .data(nodes)
                    .enter().append("circle")
                    .attr("class", "node")
                    .attr("r", 20)
                    .call(force.drag);

            force.on("tick", function () {
                node.attr("cx", function (d) {
                            return d.x;
                        })
                        .attr("cy", function (d) {
                            return d.y;
                        });
            });
        }
    }
</script>

Question

Using one XML as data the graph looks like this...

enter image description here

Using multiple XML's as data the graph looks like this...

Using multiple XML

What part of the code is causing this behaviour? I have tried to configure the x and y coordinates with hard coded values, but regardless of my attempts, the nodes just appear as a 1/4 node in the top left corner.

Reproduce

I tried to make the issue ease to reproduce using jsfiddle, but I failed to get external sources to work regardless of my attempts based on the answers from How to add local json file in jsfiddle?

Full code on github gist:

https://gist.github.com/Weirdfishees/f1b19b43346a175bd214

and on github (small directory difference)

https://github.com/Weirdfishees/xmltoforcegraph.

Community
  • 1
  • 1
Sander_M
  • 1,109
  • 2
  • 18
  • 36
  • 1
    You loop all your xml files but overwrite the nodes array each time? Is this intended? I imagine you want to build up that array. Also, your links array doesn't seem to be in the correct format. You end up with an array where source and target are strings, they should be array indexes of the nodes. – Mark Mar 20 '16 at 17:34
  • 1
    Also, here's a [plunker](http://plnkr.co/edit/Fp7B8RhLMhqBGsMHvJ5H?p=preview) (it's easier to work with external files then jsFiddle) where I started to play with your code. Without knowing what you are intending with the `links` and `nodes`, I can't help any further. – Mark Mar 20 '16 at 17:37
  • Thanks for your comment @Mark. I am not sure about the overriden the nodes array. I tried to stick as much as possible to the example from Mike Bostock linked in the question. With regard to the strings and the links, I was under the impression it was possible as long as the string objects are the same as the label of the node. I will try to rework the links part. Thanks again for your much appreciated help and the plunker advice will make my future life alot easier. ps: the intention with the links and nodes is to create a relation based on xml one-to-many and many-to-one relationship. – Sander_M Mar 20 '16 at 17:41
  • For example: Country.hbm.xml has an one-to-many relation with City. In other words, the source is country and the target is city (A country has many cities). I will try to figure out how to attach the correct node id as source and target. – Sander_M Mar 20 '16 at 17:50
  • I have managed to get a whole lot further http://plnkr.co/edit/Bx0qe8DNEsnFgLhkxbfS?p=preview All that remains is some bug fixing with the links. There are some double link objects and I think thats causing the weird drawing. @Mark Thank you for helping me once again to get a step further! :) I can't assign your comments as answers, but the information you provided did give me the answer to the question. Perhaps you could link your comment in an answer post? – Sander_M Mar 21 '16 at 00:32

0 Answers0