无法为D3条形图选择XML节点

时间:2014-01-22 13:53:30

标签: javascript xml date charts d3.js

我搜索了这个网站,发现了很多D3示例,但我很难让我的XML文件中的节点绑定到一个简单的D3条形图。这是我的XML文件:

<?xml version="1.0" encoding="UTF-8" ?>
<MTTR>
  <MONTH>
    <FixMonth>2012-12</FixMonth>
    <AvgMTTR>31.4700000</AvgMTTR>
    <DefectCaseCount>200</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-01</FixMonth>
    <AvgMTTR>38.2764976</AvgMTTR>
    <DefectCaseCount>217</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-02</FixMonth>
    <AvgMTTR>28.5416666</AvgMTTR>
    <DefectCaseCount>192</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-03</FixMonth>
    <AvgMTTR>27.8351254</AvgMTTR>
    <DefectCaseCount>279</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-04</FixMonth>
    <AvgMTTR>27.2445141</AvgMTTR>
    <DefectCaseCount>319</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-05</FixMonth>
    <AvgMTTR>26.2034632</AvgMTTR>
   <DefectCaseCount>231</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-06</FixMonth>
    <AvgMTTR>32.1470588</AvgMTTR>
    <DefectCaseCount>238</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-07</FixMonth>
    <AvgMTTR>29.6721311</AvgMTTR>
    <DefectCaseCount>244</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-08</FixMonth>
    <AvgMTTR>29.3853211</AvgMTTR>
    <DefectCaseCount>218</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-09</FixMonth>
    <AvgMTTR>28.6966824</AvgMTTR>
    <DefectCaseCount>211</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-10</FixMonth>
    <AvgMTTR>28.6500000</AvgMTTR>
    <DefectCaseCount>220</DefectCaseCount>
  </MONTH>
  <MONTH>
    <FixMonth>2013-11</FixMonth>
    <AvgMTTR>29.3197969</AvgMTTR>
    <DefectCaseCount>197</DefectCaseCount>
  </MONTH>
</MTTR>

我正在尝试使用Mike Bostock的简单条形图作为插入我的XML数据的模式,但没有运气。这是我正在使用的相关javascript代码:

--------- code snippet ------------

var dataset;
var parseDate = d3.time.format("%Y-%m").parse;

d3.xml("MTTR.xml", "application/xml", function(error, data) {

    if (error) { return console.warn(error); 

               }
    else { dataset = data;
           console.log(dataset);
           x.domain([0, d3.max(dataset, function(d) { return parseDate(d.FixMonth); })]);
           y.domain([0, d3.max(dataset, function(d) { return d.AvgMTTR; })]);

         }


  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
      .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("MTTR");

  svg.selectAll(".bar")
      .data(dataset)
      .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x(d.FixMonth); })
      .attr("width", x.rangeBand())
      .attr("y", function(d) { return y(d.AvgMTTR); })
      .attr("height", function(d) { return height - y(d.AvgMTTR); });

});

function type(d) {
  d.AvgMTTR = +d.AvgMTTR;
  return d;
}

------------结束代码片段----------

我无法让parseDate和x.domain绑定工作。我也无法将FixMonth节点解析为字符串,以将值分配给x轴。任何提示都非常感激。

1 个答案:

答案 0 :(得分:1)

我有点惊讶d3没有将XML数据转换为JSON的内置方法,但我想这是因为XML数据的结构变化很大。

对于您的数据集,所有数据值都作为标记名称而没有属性,此函数应该为您进行转换:

//a recursive function to convert simple xml to JSON
//tag names become object keys
//elements with the same tag are grouped into arrays
//tag attributes are ignored
var nestByTagName = d3.nest().key(function(d){
        return d.tagName;
    });
function xmlToJSON(xml) {
    if (xml.children.length) {
        var o = {}
        var childTypes = nestByTagName.entries(xml.children);

        childTypes.forEach(function(type) {
            //each type, as returned by the nest function
            //will be an object with type.key = tagName
            //and type.values = array of xml child objects

            if (type.values.length == 1) {
                //only one child of this type
               o[type.key] =  xmlToJSON(type.values[0]);
            }
            else { // multiple children of this type
                o[type.key] = type.values.map( function(v) {
                        return xmlToJSON(v);
                    });
                //replace each xml object in the nested array
                //with its JSON-ified version
            }

        });
        return o;
    }
    else { //leaf node, return string value
        return xml.textContent;
    }

}

使用您的数据集实现,并通过一些解决方法将其作为小提琴阅读 输出到控制台:http://fiddle.jshell.net/22E9X/1/
在3秒超时后显示结果面板中的更改:http://fiddle.jshell.net/22E9X/2/

您想要用于d3制图的数据阵列位于dataset.mttr.months。请注意,该函数不会执行任何操作来解析日期或从字符串转换数字;你仍然需要在你的访问器功能中这样做。唯一的另一个缺点是内部函数破坏了大小写混合标记名称。