Question

This is related to another question (Chart is rendered in Chrome, but not in FF and IE), however, I am of the opinion that it is a valid question in itself and this will hopefully help describing the problem more in-depth.

I realized this behavior when I opened my webpage with Firefox by chance and noticed that my amChart graph wasn't working anymore, which I traced back to these lines in the code:

xmlData = xmlHttp.responseXML;
var x=xmlData.getElementsByTagName("row");
xmlRowCount = x.length;

Apparently the Firefox & Internet Explorer engines execute "xmlData.getElementsByTagName" differently from Google Chrome (where it works fine), which in turn leads to wrong return values and therefore an utter breaking of all following code.

The question is why FF and IE do this and how to prevent them from doing it and return the proper result just like Chrome.

I appreciate any suggestions and hope that some of you can help me and might know the reason for this strange behavior.

best regards,

daZza

Edit: To make the browser test complete, I also downloaded and tested Opera. It works fine there, which makes this whole thing even stranger. What is the difference between IE/FF vs. Chrome/Opera?

EDIT2: This finding looks promising... I tried adding a second console.log message that prints out the same thing, but uses the "non namespace name" of the XML tag, in this case z:row instead of row (row is the namespace name, z:row is the hard tag in the xml file).

What I discovered is, that Firefox/IE return 417 with this new console.log on the non-namespace name. Chrome/Opera return 0. And the same is true vice-versa, so Chrome returns 417 using the namespace, while FF/IE return 0.

This leads me to believe, tha FF/IE have a broken XML DOM that cannot utilize/use/detect/... namespaces in XML files.

I guess the only fix in that case is to use a XML without a namespace so it works on all browsers?

Here's a short example of the XML file (taken from a Sharepoint API):

 <xml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
 xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
 xmlns:rs='urn:schemas-microsoft-com:rowset'
 xmlns:z='#RowsetSchema'>
 <s:Schema id='RowsetSchema'>
 <s:ElementType name='row' content='eltOnly' rs:CommandTimeout='30'>
  <s:AttributeType name='blub' rs:name='blah' rs:number='1'>
     <s:datatype dt:type='string' dt:maxLength='512' />
  </s:AttributeType>
 </s:ElementType>
 </s:Schema>
 <rs:data>
 <z:row blub="blahblah" />
 </rs:data>  
 </xml>

PS: Here's are some code snippets that might be relevant to the issue:

JS section at the bottom of the HTML header (this is where the error occurs):

var xmlRowCount;

var arrArt = new Array();
var arrPriority = new Array();
var arrTermin = new Array();
var arrResult = new Array();

var arrCalcPrio = new Array();
var avgCalcPrio = new Array();

var terminCounter = 0;
var avgCounter = 0;

 // button_bereichand button_unterbereich are the values from two dropdown boxes. --> Shouldn't have relevance for the problem at hand. The xmlFile parameter is an well formed and validated XML file within the same domain.

function loadXML(xmlFile, button_bereich, button_unterbereich)
{

    var xmlHttp = null;
    var xmlData;
    var sum = 0;
    var bereich = button_bereich;
    var unterbereich = button_unterbereich;
    var spUnterbereich = "";

    console.log("Bereich: " + bereich);
    console.log("Unterbereich: " + unterbereich);

    arrArt.length = 0;
    arrPriority.length = 0;
    arrCalcPrio.length = 0;

    if (typeof XMLHttpRequest != 'undefined')
    {
        xmlHttp = new XMLHttpRequest();
    }

    if (!xmlHttp)
    {
        try
        {
            xmlHttp = new ActiveXObject("Msxm12.XMLHTTP");

        } 
        catch(e)
        {
            try
            {
                xmlHttp = new ActiveXObject("Mircosoft.XMLHTTP")

            } 
            catch(e)
            {
                xmlHttp = null;
            }
        }
    }

    if (xmlHttp)
    {
        var url = xmlFile;
        xmlHttp.open("GET", url, true);
        xmlHttp.onreadystatechange = function() 
        {
            if (xmlHttp.readyState == 4)
            {
                var txt="";
                xmlData = xmlHttp.responseXML;
                var x=xmlData.getElementsByTagName("row");

                xmlRowCount = x.length;

                // Chrome: 417 | Firefox: 0 | Internet Explorer: 0
                console.log("Rowcount: " + xmlRowCount);

                for (i=0;i<xmlRowCount;i++)
                {
                    // do something with each row
                }

                for (j=0;j<xmlRowCount-1;)
                {   
                    // do something
                }

            }   
            }
        }
        xmlHttp.send();
    }

    return xmlData;
}


// bereichElement and bereichText are the values from two dropdown boxes. --> Shouldn't have relevance for the problem at hand
function getGraph()
{
    chartData.length = 0;
    validateData();

    var bereichElement = document.getElementById("bereich");
    var bereichText = bereichElement.options[bereichElement.selectedIndex].text;
    var unterbereichElement = document.getElementById("unterbereich");
    var unterbereichText = unterbereichElement.options[unterbereichElement.selectedIndex].text;

    var xmlDoc=loadXML("sp_xml.xml", bereichText, unterbereichText);
}

JS in HTML Body( Body has body onload="getGraph();"> parameter):

// Actual chart creation (amCharts lib)
 var chart;
        var chartData = [];
        var chartCursor;

        AmCharts.ready(function() {

            // SERIAL CHART
            chart = new AmCharts.AmSerialChart();
            chart.pathToImages = "amcharts/images/";
            chart.dataProvider = chartData;
            chart.categoryField = "date";
            chart.dataDateFormat = "YYYY-MM-DD";
            chart.baseHref = true;

            // listen for "dataUpdated" event (fired when chart is rendered) and call zoomChart method when it happens
            chart.addListener("dataUpdated", zoomChart);

            // AXES
            // category
            var categoryAxis = chart.categoryAxis;
            categoryAxis.parseDates = true; 
            categoryAxis.minPeriod = "DD"; 
            categoryAxis.dashLength = 1;
            categoryAxis.gridAlpha = 0.15;
            categoryAxis.minorGridEnabled = true;
            categoryAxis.axisColor = "#DADADA";

            // value
            var valueAxis = new AmCharts.ValueAxis();
            valueAxis.axisAlpha = 0.2;
            valueAxis.dashLength = 1;
            chart.addValueAxis(valueAxis);

            // GRAPH
            var graph = new AmCharts.AmGraph();
            graph.title = "red line";
            graph.valueField = "visits";
            graph.bullet = "round";
            graph.bulletBorderColor = "#FFFFFF";
            graph.bulletBorderThickness = 2;
            graph.bulletBorderAlpha = 1;
            graph.lineThickness = 2;
            graph.lineColor = "#0db503";
            graph.negativeLineColor = "#b5030d";
            graph.balloonText = "[[category]]<br><b><span style='font-size:14px;'>value: [[value]]</span></b>";
            graph.hideBulletsCount = 50; 
            chart.addGraph(graph);

            // CURSOR
            chartCursor = new AmCharts.ChartCursor();
            chartCursor.cursorPosition = "mouse";
            chart.addChartCursor(chartCursor);

            // SCROLLBAR
            var chartScrollbar = new AmCharts.ChartScrollbar();
            chartScrollbar.graph = graph;
            chartScrollbar.scrollbarHeight = 40;
            chartScrollbar.color = "#FFFFFF";
            chartScrollbar.autoGridCount = true;
            chart.addChartScrollbar(chartScrollbar);

            // WRITE
            chart.write("charts_container");

        });




         // this method is called when chart is first inited as we listen for "dataUpdated" event
        function zoomChart() {
            // different zoom methods can be used - zoomToIndexes, zoomToDates, zoomToCategoryValues
            chart.zoomToIndexes(chartData.length - 40, chartData.length - 1);
        }

         // changes cursor mode from pan to select
        function setPanSelect() {
            if (document.getElementById("rb1").checked) {
                chartCursor.pan = false;
                chartCursor.zoomable = true;

            } else {
                chartCursor.pan = true;
            }
            chart.validateNow();
        }

        function validateData()
        {
            chart.validateData();
            console.log("Data validated");

        }
Was it helpful?

Solution

Your issue is that getElementsByTagName as specified in http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-A6C9094 specified matching on the "tagname", not the local name, and the tag name includes the prefix (see http://www.w3.org/TR/2004/REC-DOM-Level-3-Core-20040407/core.html#ID-104682815 where it explicitly says the tagName is the qualified name).

That's the behavior Firefox and IE implement.

WebKit never implemented that spec correctly, matching only on localName instead, as far as I can tell.

You can work around that by using getElementsByTagNameNS, which lets you explicitly match on localname only in all modern browsers. You can either pass in your actual namespace, or just "*" if you don't care about the namespace part.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top