Search code examples
c#xmldocumentgoogle-analytics-api

XmlDocument from google analytics to flat file c#


Using C# I have extracted data from Google Analytics Data API and have got it in an xmldocument. From that point I want to export it to flat file format (txt file). I am trying to use the xmlnode class to write out element attribute values within the 'entry' elements but cant do it. XML code below:

<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:dxp="http://schemas.google.com/analytics/2009" xmlns:openSearch="http://a9.com/-    /spec/opensearch/1.1/">
  <id>https://www.googleapis.com/analytics/v2.4/data?ids=ga:xxxxxxxxx&amp;dimensions=ga:date,ga:hostname&amp;metrics=ga:visits,ga:newVisits,ga:visitBounceRate,ga:transactions,ga:transactionRevenue,ga:itemQuantity&amp;start-date=2012-09-20&amp;end-date=2012-09-26&amp;start-index=1&amp;max-results=1000</id>
  <updated>2012-09-27T08:08:53.621Z</updated>
  <title type="text">Google Analytics Data for Profile xxxxxxxxx</title>
  <link rel="self" type="application/atom+xml" href="https://www.googleapis.com/analytics/v2.4/data?ids=ga:xxxxxxxxx&amp;dimensions=ga:date,ga:hostname&amp;metrics=ga:visits,ga:newVisits,ga:visitBounceRate,ga:transactions,ga:transactionRevenue,ga:itemQuantity&amp;start-date=2012-09-20&amp;end-date=2012-09-26&amp;start-index=1&amp;max-results=1000" />
  <author>
    <name>Google Analytics</name>
  </author>
  <generator>Google Analytics</generator>
  <openSearch:totalResults>49</openSearch:totalResults>
  <openSearch:startIndex>1</openSearch:startIndex>
  <openSearch:itemsPerPage>1000</openSearch:itemsPerPage>
  <dxp:aggregates>
    <dxp:metric name="ga:visits" type="integer" value="942258" />
    <dxp:metric name="ga:newVisits" type="integer" value="393698" />
    <dxp:metric name="ga:visitBounceRate" type="percent" value="26.960025810340692" />
    <dxp:metric name="ga:transactions" type="integer" value="328" />
    <dxp:metric name="ga:transactionRevenue" type="currency" value="427646.331187" />
    <dxp:metric name="ga:itemQuantity" type="integer" value="322" />
  </dxp:aggregates>
  <dxp:containsSampledData>true</dxp:containsSampledData>
  <dxp:dataSource>
    <dxp:property name="ga:profileId" value="xxxxxxxxx" />
    <dxp:property name="ga:webPropertyId" value="UA-33036832-1" />
    <dxp:property name="ga:accountName" value="TCO-UK-TC.com-[thomascook.com]" />
    <dxp:tableId>ga:xxxxxxxxx</dxp:tableId>
    <dxp:tableName>ThomasCook UK - Analytics Extract (VP /search)</dxp:tableName>
  </dxp:dataSource>
  <dxp:endDate>2012-09-26</dxp:endDate>
  <dxp:startDate>2012-09-20</dxp:startDate>
  <entry>
    <id>https://www.googleapis.com/analytics/v2.4/data?ids=ga:xxxxxxxxx&amp;ga:date=20120920&amp;ga:hostname=87.248.112.8&amp;start-date=2012-09-20&amp;end-date=2012-09-26</id>
    <updated>2012-09-27T08:08:53.621Z</updated>
    <title type="text">ga:date=20120920 | ga:hostname=87.248.112.8</title>
    <link rel="alternate" type="text/html" href="http://www.google.com/analytics" />
    <dxp:dimension name="ga:date" value="20120920" />
    <dxp:dimension name="ga:hostname" value="87.248.112.8" />
    <dxp:metric name="ga:visits" type="integer" value="3" />
    <dxp:metric name="ga:newVisits" type="integer" value="3" />
    <dxp:metric name="ga:visitBounceRate" type="percent" value="100.0" />
    <dxp:metric name="ga:transactions" type="integer" value="0" />
    <dxp:metric name="ga:transactionRevenue" type="currency" value="0.0" />
    <dxp:metric name="ga:itemQuantity" type="integer" value="0" />
  </entry>
  <entry>
    <id>https://www.googleapis.com/analytics/v2.4/data?ids=ga:xxxxxxxxx&amp;ga:date=20120920&amp;ga:hostname=alpha.thomascook.com&amp;start-date=2012-09-20&amp;end-date=2012-09-26</id>
    <updated>2012-09-27T08:08:53.621Z</updated>
    <title type="text">ga:date=20120920 | ga:hostname=alpha.thomascook.com</title>
    <link rel="alternate" type="text/html" href="http://www.google.com/analytics" />
    <dxp:dimension name="ga:date" value="20120920" />
    <dxp:dimension name="ga:hostname" value="alpha.thomascook.com" />
    <dxp:metric name="ga:visits" type="integer" value="160" />
    <dxp:metric name="ga:newVisits" type="integer" value="109" />
    <dxp:metric name="ga:visitBounceRate" type="percent" value="21.25" />
    <dxp:metric name="ga:transactions" type="integer" value="0" />
    <dxp:metric name="ga:transactionRevenue" type="currency" value="0.0" />
    <dxp:metric name="ga:itemQuantity" type="integer" value="0" />
  </entry>
  ....so on.....

In the code below I need to change it to locate the entry elements, but can't find it. Using "/entry" yields nothing.

XmlNamespaceManager xmlnsm = new XmlNamespaceManager(xmld.NameTable);
xmlnsm.AddNamespace("dxp", "http://schemas.google.com/analytics/2009");
xmlnsm.AddNamespace("openSearch", "http://a9.com/-/spec/opensearch/1.1/");
xmlnsm.AddNamespace("gd", "http://schemas.google.com/g/2005");

foreach (XmlNode xmlnd in xmld.SelectNodes("//dxp:dimension", xmlnsm))
{
    DimVal = xmlnd.Attributes["value"].Value.ToString();
    DimName = xmlnd.Attributes["name"].Value.Replace("ga:", "");
    // ...
}

I could be missing a namespace. Can anyone please help me out?


Solution

  • XDocument xDoc = XDocument.Load(fileToLoad); //or XDocument.Parse(xmlString)
    XNamespace dxp = "http://schemas.google.com/analytics/2009";
    XNamespace ns = "http://www.w3.org/2005/Atom";
    
    var result =
        xDoc.Descendants(ns + "entry")
        .Select(e => new
        {
            Dimension = e.Descendants(dxp + "dimension")
                         .ToDictionary(d => d.Attribute("name").Value, d => d.Attribute("value").Value),
            Metric = e.Descendants(dxp + "metric")
                      .ToDictionary(d => d.Attribute("name").Value, d => d.Attribute("value").Value)
        })
        .ToList();
    

    Print the result:

    foreach(var entry in result)
    {
        foreach (var dim in entry.Dimension) 
              Console.WriteLine(dim.Key + " = " + dim.Value);
        Console.WriteLine();
    
        foreach (var met in entry.Metric) 
              Console.WriteLine(met.Key + " = " + met.Value);
        Console.WriteLine("---------------");
    }