private function renderArray($array, $prefixLines)
    {
        $isAssociativeArray = Piwik::isAssociativeArray($array);

        // check if array contains arrays, and if not wrap the result in an extra <row> element
        // (only check if this is the root renderArray call)
        // NOTE: this is for backwards compatibility. before, array's were added to a new DataTable.
        // if the array had arrays, they were added as multiple rows, otherwise it was treated as
        // one row. removing will change API output.
        $wrapInRow = $prefixLines === "\t"
            && self::shouldWrapArrayBeforeRendering($array, $wrapSingleValues = false, $isAssociativeArray);

        // render the array
        $result = "";
        if ($wrapInRow) {
            $result .= "$prefixLines<row>\n";
            $prefixLines .= "\t";
        }
        foreach ($array as $key => $value) {
            // based on the type of array & the key, determine how this node will look
            if ($isAssociativeArray) {
                if (strpos($key, '=') !== false) {
                    list($keyAttributeName, $key) = explode('=', $key, 2);

                    $prefix = "<row $keyAttributeName=\"$key\">";
                    $suffix = "</row>";
                    $emptyNode = "<row $keyAttributeName=\"$key\">";
                } elseif (!self::isValidXmlTagName($key)) {
                    $prefix = "<row key=\"$key\">";
                    $suffix = "</row>";
                    $emptyNode = "<row key=\"$key\"/>";
                } else {
                    $prefix = "<$key>";
                    $suffix = "</$key>";
                    $emptyNode = "<$key />";
                }
            } else {
                $prefix = "<row>";
                $suffix = "</row>";
                $emptyNode = "<row/>";
            }

            // render the array item
            if (is_array($value) || $value instanceof \stdClass) {
                $result .= $prefixLines . $prefix . "\n";
                $result .= $this->renderArray((array) $value, $prefixLines . "\t");
                $result .= $prefixLines . $suffix . "\n";
            } elseif ($value instanceof DataTable
                || $value instanceof Map
            ) {
                if ($value->getRowsCount() == 0) {
                    $result .= $prefixLines . $emptyNode . "\n";
                } else {
                    $result .= $prefixLines . $prefix . "\n";
                    if ($value instanceof Map) {
                        $result .= $this->renderDataTableMap($value, $this->getArrayFromDataTable($value), $prefixLines);
                    } elseif ($value instanceof Simple) {
                        $result .= $this->renderDataTableSimple($this->getArrayFromDataTable($value), $prefixLines);
                    } else {
                        $result .= $this->renderDataTable($this->getArrayFromDataTable($value), $prefixLines);
                    }
                    $result .= $prefixLines . $suffix . "\n";
                }
            } else {
                $xmlValue = self::formatValueXml($value);

                if (strlen($xmlValue) != 0) {
                    $result .= $prefixLines . $prefix . $xmlValue . $suffix . "\n";
                } else {
                    $result .= $prefixLines . $emptyNode . "\n";
                }
            }
        }
        if ($wrapInRow) {
            $result .= substr($prefixLines, 0, strlen($prefixLines) - 1) . "</row>\n";
        }
        return $result;
    }