uva-happymapper 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. data/README.md +528 -0
  2. data/TODO +0 -0
  3. data/lib/happymapper.rb +617 -0
  4. data/lib/happymapper/attribute.rb +3 -0
  5. data/lib/happymapper/element.rb +3 -0
  6. data/lib/happymapper/item.rb +250 -0
  7. data/lib/happymapper/text_node.rb +3 -0
  8. data/spec/fixtures/address.xml +8 -0
  9. data/spec/fixtures/ambigous_items.xml +22 -0
  10. data/spec/fixtures/analytics.xml +61 -0
  11. data/spec/fixtures/analytics_profile.xml +127 -0
  12. data/spec/fixtures/atom.xml +19 -0
  13. data/spec/fixtures/commit.xml +52 -0
  14. data/spec/fixtures/current_weather.xml +89 -0
  15. data/spec/fixtures/dictionary.xml +20 -0
  16. data/spec/fixtures/family_tree.xml +21 -0
  17. data/spec/fixtures/inagy.xml +86 -0
  18. data/spec/fixtures/lastfm.xml +355 -0
  19. data/spec/fixtures/multiple_namespaces.xml +170 -0
  20. data/spec/fixtures/multiple_primitives.xml +5 -0
  21. data/spec/fixtures/pita.xml +133 -0
  22. data/spec/fixtures/posts.xml +23 -0
  23. data/spec/fixtures/product_default_namespace.xml +17 -0
  24. data/spec/fixtures/product_no_namespace.xml +10 -0
  25. data/spec/fixtures/product_single_namespace.xml +10 -0
  26. data/spec/fixtures/quarters.xml +19 -0
  27. data/spec/fixtures/radar.xml +21 -0
  28. data/spec/fixtures/statuses.xml +422 -0
  29. data/spec/fixtures/subclass_namespace.xml +50 -0
  30. data/spec/happymapper_attribute_spec.rb +21 -0
  31. data/spec/happymapper_element_spec.rb +21 -0
  32. data/spec/happymapper_item_spec.rb +115 -0
  33. data/spec/happymapper_spec.rb +968 -0
  34. data/spec/happymapper_text_node_spec.rb +21 -0
  35. data/spec/happymapper_to_xml_namespaces_spec.rb +196 -0
  36. data/spec/happymapper_to_xml_spec.rb +196 -0
  37. data/spec/ignay_spec.rb +95 -0
  38. data/spec/spec_helper.rb +7 -0
  39. data/spec/xpath_spec.rb +88 -0
  40. metadata +118 -0
@@ -0,0 +1,3 @@
1
+ module HappyMapper
2
+ class Attribute < Item; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module HappyMapper
2
+ class Element < Item; end
3
+ end
@@ -0,0 +1,250 @@
1
+ module HappyMapper
2
+ class Item
3
+ attr_accessor :name, :type, :tag, :options, :namespace
4
+
5
+ Types = [String, Float, Time, Date, DateTime, Integer, Boolean]
6
+
7
+ # options:
8
+ # :deep => Boolean False to only parse element's children, True to include
9
+ # grandchildren and all others down the chain (// in xpath)
10
+ # :namespace => String Element's namespace if it's not the global or inherited
11
+ # default
12
+ # :parser => Symbol Class method to use for type coercion.
13
+ # :raw => Boolean Use raw node value (inc. tags) when parsing.
14
+ # :single => Boolean False if object should be collection, True for single object
15
+ # :tag => String Element name if it doesn't match the specified name.
16
+ def initialize(name, type, o={})
17
+ self.name = name.to_s
18
+ self.type = type
19
+ #self.tag = o.delete(:tag) || name.to_s
20
+ self.tag = o[:tag] || name.to_s
21
+ self.options = { :single => true }.merge(o.merge(:name => self.name))
22
+
23
+ @xml_type = self.class.to_s.split('::').last.downcase
24
+ end
25
+
26
+ def constant
27
+ @constant ||= constantize(type)
28
+ end
29
+
30
+ #
31
+ # @param [XMLNode] node the xml node that is being parsed
32
+ # @param [String] namespace the name of the namespace
33
+ # @param [Hash] xpath_options additional xpath options
34
+ #
35
+ def from_xml_node(node, namespace, xpath_options)
36
+
37
+ # If the item is defined as a primitive type then cast the value to that type
38
+ # else if the type is XMLContent then store the xml value
39
+ # else the type, specified, needs to handle the parsing.
40
+
41
+ if primitive?
42
+ find(node, namespace, xpath_options) do |n|
43
+ if n.respond_to?(:content)
44
+ typecast(n.content)
45
+ else
46
+ typecast(n.to_s)
47
+ end
48
+ end
49
+ elsif constant == XmlContent
50
+ find(node, namespace, xpath_options) do |n|
51
+ n = n.children if n.respond_to?(:children)
52
+ n.respond_to?(:to_xml) ? n.to_xml : n.to_s
53
+ end
54
+ else
55
+
56
+ # When not a primitive type or XMLContent then default to using the
57
+ # class method #parse of the type class. If the option 'parser' has been
58
+ # defined then call that method on the type class instead of #parse
59
+
60
+ if options[:parser]
61
+ find(node, namespace, xpath_options) do |n|
62
+ if n.respond_to?(:content) && !options[:raw]
63
+ value = n.content
64
+ else
65
+ value = n.to_s
66
+ end
67
+
68
+ begin
69
+ constant.send(options[:parser].to_sym, value)
70
+ rescue
71
+ nil
72
+ end
73
+ end
74
+ else
75
+ constant.parse(node, options.merge(:namespaces => xpath_options))
76
+ end
77
+ end
78
+ end
79
+
80
+ def xpath(namespace = self.namespace)
81
+ xpath = ''
82
+ xpath += './/' if options[:deep]
83
+ xpath += "#{namespace}:" if namespace
84
+ xpath += tag
85
+ #puts "xpath: #{xpath}"
86
+ xpath
87
+ end
88
+
89
+ # @return [Boolean] true if the type defined for the item is defined in the
90
+ # list of primite types {Types}.
91
+ def primitive?
92
+ Types.include?(constant)
93
+ end
94
+
95
+ def element?
96
+ @xml_type == 'element'
97
+ end
98
+
99
+ def attribute?
100
+ @xml_type == 'attribute'
101
+ end
102
+
103
+ def text_node?
104
+ @xml_type == 'textnode'
105
+ end
106
+
107
+ def method_name
108
+ @method_name ||= name.tr('-', '_')
109
+ end
110
+
111
+ #
112
+ # When the type of the item is a primitive type, this will convert value specifed
113
+ # to the particular primitive type. If it fails during this process it will
114
+ # return the original String value.
115
+ #
116
+ # @param [String] value the string value parsed from the XML value that will
117
+ # be converted to the particular primitive type.
118
+ #
119
+ # @return [String,Float,Time,Date,DateTime,Boolean,Integer] the converted value
120
+ # to the new type.
121
+ #
122
+ def typecast(value)
123
+ return value if value.kind_of?(constant) || value.nil?
124
+ begin
125
+ if constant == String then value.to_s
126
+ elsif constant == Float then value.to_f
127
+ elsif constant == Time then Time.parse(value.to_s) rescue Time.at(value.to_i)
128
+ elsif constant == Date then Date.parse(value.to_s)
129
+ elsif constant == DateTime then DateTime.parse(value.to_s)
130
+ elsif constant == Boolean then ['true', 't', '1'].include?(value.to_s.downcase)
131
+ elsif constant == Integer
132
+ # ganked from datamapper
133
+ value_to_i = value.to_i
134
+ if value_to_i == 0 && value != '0'
135
+ value_to_s = value.to_s
136
+ begin
137
+ Integer(value_to_s =~ /^(\d+)/ ? $1 : value_to_s)
138
+ rescue ArgumentError
139
+ nil
140
+ end
141
+ else
142
+ value_to_i
143
+ end
144
+ else
145
+ value
146
+ end
147
+ rescue
148
+ value
149
+ end
150
+ end
151
+
152
+ private
153
+
154
+ #
155
+ # Convert any String defined types into their constant version so that
156
+ # the method #parse or the custom defined parser method would be used.
157
+ #
158
+ # @param [String,Constant] type is the name of the class or the constant
159
+ # for the class.
160
+ # @return [Constant] the constant of the type
161
+ #
162
+ def constantize(type)
163
+ if type.is_a?(String)
164
+ names = type.split('::')
165
+ constant = Object
166
+ names.each do |name|
167
+ constant =
168
+ if constant.const_defined?(name)
169
+ constant.const_get(name)
170
+ else
171
+ constant.const_missing(name)
172
+ end
173
+ end
174
+ constant
175
+ else
176
+ type
177
+ end
178
+ end
179
+
180
+
181
+ def find(node, namespace, xpath_options, &block)
182
+ if self.namespace && xpath_options["xmlns:#{self.namespace}"]
183
+ # from the class definition
184
+ namespace = self.namespace
185
+ elsif options[:namespace] && xpath_options["xmlns:#{options[:namespace]}"]
186
+ namespace = options[:namespace]
187
+ end
188
+
189
+ if element?
190
+ if options[:single]
191
+
192
+ result = nil
193
+
194
+ if options[:xpath]
195
+ result = node.xpath(options[:xpath], xpath_options)
196
+ else
197
+ result = node.xpath(xpath(namespace), xpath_options)
198
+ end
199
+
200
+ if result
201
+ value = options[:single] ? yield(result.first) : result.map {|r| yield r }
202
+ handle_attributes_option(result, value, xpath_options)
203
+
204
+ value
205
+ end
206
+ else
207
+
208
+ target_path = options[:xpath] ? options[:xpath] : xpath(namespace)
209
+
210
+ results = node.xpath(target_path, xpath_options).collect do |result|
211
+ value = yield(result)
212
+ handle_attributes_option(result, value, xpath_options)
213
+ value
214
+ end
215
+ results
216
+ end
217
+ elsif attribute?
218
+
219
+ if options[:xpath]
220
+ yield(node.xpath(options[:xpath],xpath_options))
221
+ else
222
+ yield(node[tag])
223
+ end
224
+
225
+ else # text node
226
+ yield(node.children.detect{|c| c.text?})
227
+ end
228
+ end
229
+
230
+ def handle_attributes_option(result, value, xpath_options)
231
+ if options[:attributes].is_a?(Hash)
232
+ result = result.first unless result.respond_to?(:attribute_nodes)
233
+
234
+ result.attribute_nodes.each do |xml_attribute|
235
+ if attribute_options = options[:attributes][xml_attribute.name.to_sym]
236
+ attribute_value = Attribute.new(xml_attribute.name.to_sym, *attribute_options).from_xml_node(result, namespace, xpath_options)
237
+
238
+ result.instance_eval <<-EOV
239
+ def value.#{xml_attribute.name}
240
+ #{attribute_value.inspect}
241
+ end
242
+ EOV
243
+ end # if attributes_options
244
+ end # attribute_nodes.each
245
+ end # if options[:attributes]
246
+ end # def handle...
247
+
248
+ # end private methods
249
+ end
250
+ end
@@ -0,0 +1,3 @@
1
+ module HappyMapper
2
+ class TextNode < Item; end
3
+ end
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <address>
3
+ <street>Milchstrasse</street>
4
+ <housenumber>23</housenumber>
5
+ <postcode>26131</postcode>
6
+ <city>Oldenburg</city>
7
+ <country code="de">Germany</country>
8
+ </address>
@@ -0,0 +1,22 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <ambigous>
3
+ <my-items>
4
+ <item>
5
+ <name>My first item</name>
6
+ <item><name>My first internal item</name></item>
7
+ </item>
8
+ <item>
9
+ <name>My second item</name>
10
+ <item><name>My second internal item</name></item>
11
+ </item>
12
+ <item>
13
+ <name>My third item</name>
14
+ <item><name>My third internal item</name></item>
15
+ </item>
16
+ </my-items>
17
+ <others-items>
18
+ <item>
19
+ <name>Other item</name>
20
+ </item>
21
+ <others-items>
22
+ </ambigous>
@@ -0,0 +1,61 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <feed xmlns="http://www.w3.org/2005/Atom"
3
+ xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/"
4
+ xmlns:dxp="http://schemas.google.com/analytics/2009">
5
+ <id>http://www.google.com/analytics/feeds/accounts/nunemaker@gmail.com</id>
6
+ <updated>2009-04-22T23:21:23.000-07:00</updated>
7
+ <title type="text">Profile list for nunemaker@gmail.com</title>
8
+ <link rel="self" type="application/atom+xml"
9
+ href="http://www.google.com/analytics/feeds/accounts/default"/>
10
+ <author>
11
+ <name>Google Analytics</name>
12
+ </author>
13
+ <generator version="1.0">Google Analytics</generator>
14
+ <openSearch:totalResults>4</openSearch:totalResults>
15
+ <openSearch:startIndex>1</openSearch:startIndex>
16
+ <openSearch:itemsPerPage>4</openSearch:itemsPerPage>
17
+ <entry>
18
+ <id>http://www.google.com/analytics/feeds/accounts/ga:47912</id>
19
+ <updated>2008-11-24T12:11:32.000-08:00</updated>
20
+ <title type="text">addictedtonew.com</title>
21
+ <link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
22
+ <dxp:tableId>ga:47912</dxp:tableId>
23
+ <dxp:property name="ga:accountId" value="85301"/>
24
+ <dxp:property name="ga:accountName" value="addictedtonew.com"/>
25
+ <dxp:property name="ga:profileId" value="47912"/>
26
+ <dxp:property name="ga:webPropertyId" value="UA-85301-1"/>
27
+ </entry>
28
+ <entry>
29
+ <id>http://www.google.com/analytics/feeds/accounts/ga:1897579</id>
30
+ <updated>2008-11-24T12:11:32.000-08:00</updated>
31
+ <title type="text">railstips.org</title>
32
+ <link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
33
+ <dxp:tableId>ga:1897579</dxp:tableId>
34
+ <dxp:property name="ga:accountId" value="85301"/>
35
+ <dxp:property name="ga:accountName" value="addictedtonew.com"/>
36
+ <dxp:property name="ga:profileId" value="1897579"/>
37
+ <dxp:property name="ga:webPropertyId" value="UA-85301-7"/>
38
+ </entry>
39
+ <entry>
40
+ <id>http://www.google.com/analytics/feeds/accounts/ga:17132454</id>
41
+ <updated>2009-04-22T23:21:23.000-07:00</updated>
42
+ <title type="text">johnnunemaker.com</title>
43
+ <link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
44
+ <dxp:tableId>ga:17132454</dxp:tableId>
45
+ <dxp:property name="ga:accountId" value="85301"/>
46
+ <dxp:property name="ga:accountName" value="addictedtonew.com"/>
47
+ <dxp:property name="ga:profileId" value="17132454"/>
48
+ <dxp:property name="ga:webPropertyId" value="UA-85301-25"/>
49
+ </entry>
50
+ <entry>
51
+ <id>http://www.google.com/analytics/feeds/accounts/ga:17132478</id>
52
+ <updated>2009-04-22T23:21:23.000-07:00</updated>
53
+ <title type="text">harmonyapp.com</title>
54
+ <link rel="alternate" type="text/html" href="http://www.google.com/analytics"/>
55
+ <dxp:tableId>ga:17132478</dxp:tableId>
56
+ <dxp:property name="ga:accountId" value="85301"/>
57
+ <dxp:property name="ga:accountName" value="addictedtonew.com"/>
58
+ <dxp:property name="ga:profileId" value="17132478"/>
59
+ <dxp:property name="ga:webPropertyId" value="UA-85301-26"/>
60
+ </entry>
61
+ </feed>
@@ -0,0 +1,127 @@
1
+ <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/' xmlns:gd='http://schemas.google.com/g/2005' gd:etag='W/&quot;CU4CSXo_cCp7I2A9Wx9RGU0.&quot;' gd:kind='analytics#accounts'>
2
+ <id>http://www.google.com/analytics/feeds/accounts/someuser@gmail.com</id>
3
+ <updated>2010-12-20T19:59:28.448-08:00</updated>
4
+ <title>Profile list for someuser@gmail.com</title>
5
+ <link rel='self' type='application/atom+xml' href='https://www.google.com/analytics/feeds/accounts/default'/>
6
+ <author>
7
+ <name>Google Analytics</name>
8
+ </author>
9
+ <generator version='1.0'>Google Analytics</generator>
10
+ <openSearch:totalResults>9</openSearch:totalResults>
11
+ <openSearch:startIndex>1</openSearch:startIndex>
12
+ <openSearch:itemsPerPage>9</openSearch:itemsPerPage>
13
+ <dxp:segment id='gaid::-1' name='All Visits'>
14
+ <dxp:definition> </dxp:definition>
15
+ </dxp:segment>
16
+ <dxp:segment id='gaid::-2' name='New Visitors'>
17
+ <dxp:definition>ga:visitorType==New Visitor</dxp:definition>
18
+ </dxp:segment>
19
+ <dxp:segment id='gaid::-3' name='Returning Visitors'>
20
+ <dxp:definition>ga:visitorType==Returning Visitor</dxp:definition>
21
+ </dxp:segment>
22
+ <dxp:segment id='gaid::-4' name='Paid Search Traffic'>
23
+ <dxp:definition>ga:medium==cpa,ga:medium==cpc,ga:medium==cpm,ga:medium==cpp,ga:medium==cpv,ga:medium==ppc</dxp:definition>
24
+ </dxp:segment>
25
+ <dxp:segment id='gaid::-5' name='Non-paid Search Traffic'>
26
+ <dxp:definition>ga:medium==organic</dxp:definition>
27
+ </dxp:segment>
28
+ <dxp:segment id='gaid::-6' name='Search Traffic'>
29
+ <dxp:definition>ga:medium==cpa,ga:medium==cpc,ga:medium==cpm,ga:medium==cpp,ga:medium==cpv,ga:medium==organic,ga:medium==ppc</dxp:definition>
30
+ </dxp:segment>
31
+ <dxp:segment id='gaid::-7' name='Direct Traffic'>
32
+ <dxp:definition>ga:medium==(none)</dxp:definition>
33
+ </dxp:segment>
34
+ <dxp:segment id='gaid::-8' name='Referral Traffic'>
35
+ <dxp:definition>ga:medium==referral</dxp:definition>
36
+ </dxp:segment>
37
+ <dxp:segment id='gaid::-9' name='Visits with Conversions'>
38
+ <dxp:definition>ga:goalCompletionsAll&gt;0</dxp:definition>
39
+ </dxp:segment>
40
+ <dxp:segment id='gaid::-10' name='Visits with Transactions'>
41
+ <dxp:definition>ga:transactions&gt;0</dxp:definition>
42
+ </dxp:segment>
43
+ <dxp:segment id='gaid::-11' name='Mobile Traffic'>
44
+ <dxp:definition>ga:isMobile==Yes</dxp:definition>
45
+ </dxp:segment>
46
+ <dxp:segment id='gaid::-12' name='Non-bounce Visits'>
47
+ <dxp:definition>ga:bounces==0</dxp:definition>
48
+ </dxp:segment>
49
+ <entry gd:etag='W/&quot;CkENQXs9fip7I2A9Wx5SE0w.&quot;' gd:kind='analytics#account'>
50
+ <id>http://www.google.com/analytics/feeds/accounts/ga:123456</id>
51
+ <updated>2010-08-08T16:38:10.566-07:00</updated>
52
+ <title>www.homedepot.com</title>
53
+ <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
54
+ <dxp:property name='ga:accountId' value='254087'/>
55
+ <dxp:property name='ga:accountName' value='www.homechefdepot.com'/>
56
+ <dxp:property name='ga:profileId' value='123456'/>
57
+ <dxp:property name='ga:webPropertyId' value='UA-254087-1'/>
58
+ <dxp:property name='ga:currency' value='USD'/>
59
+ <dxp:property name='ga:timezone' value='America/Los_Angeles'/>
60
+ <dxp:tableId>ga:123456</dxp:tableId>
61
+ </entry>
62
+ <entry gd:etag='W/&quot;C0YESXcyfyp7I2A9Wx9SFkU.&quot;' gd:kind='analytics#account'>
63
+ <id>http://www.google.com/analytics/feeds/accounts/ga:8575980</id>
64
+ <updated>2010-12-06T16:18:28.997-08:00</updated>
65
+ <title>www.pda.org</title>
66
+ <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
67
+ <dxp:property name='ga:accountId' value='4277553'/>
68
+ <dxp:property name='ga:accountName' value='www.pdma.org'/>
69
+ <dxp:property name='ga:profileId' value='8575980'/>
70
+ <dxp:property name='ga:webPropertyId' value='UA-4277553-1'/>
71
+ <dxp:property name='ga:currency' value='USD'/>
72
+ <dxp:property name='ga:timezone' value='America/Los_Angeles'/>
73
+ <dxp:tableId>ga:8575980</dxp:tableId>
74
+ </entry>
75
+ <entry gd:etag='W/&quot;CU4CSXo_cCp7I2A9Wx9RGU0.&quot;' gd:kind='analytics#account'>
76
+ <id>http://www.google.com/analytics/feeds/accounts/ga:25620226</id>
77
+ <updated>2010-12-20T19:59:28.448-08:00</updated>
78
+ <title>business.com</title>
79
+ <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
80
+ <dxp:property name='ga:accountId' value='12312214'/>
81
+ <dxp:property name='ga:accountName' value='business.com'/>
82
+ <dxp:property name='ga:profileId' value='25620226'/>
83
+ <dxp:property name='ga:webPropertyId' value='UA-12312214-1'/>
84
+ <dxp:property name='ga:currency' value='USD'/>
85
+ <dxp:property name='ga:timezone' value='America/Los_Angeles'/>
86
+ <dxp:tableId>ga:25620226</dxp:tableId>
87
+ </entry>
88
+ <entry gd:etag='W/&quot;CU4CSX0yfCp7I2A9Wx9RGU0.&quot;' gd:kind='analytics#account'>
89
+ <id>http://www.google.com/analytics/feeds/accounts/ga:12123131</id>
90
+ <updated>2010-12-20T19:59:28.394-08:00</updated>
91
+ <title>blog.com</title>
92
+ <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
93
+ <dxp:property name='ga:accountId' value='12312214'/>
94
+ <dxp:property name='ga:accountName' value='business.com'/>
95
+ <dxp:property name='ga:profileId' value='12123131'/>
96
+ <dxp:property name='ga:webPropertyId' value='UA-12345678-1'/>
97
+ <dxp:property name='ga:currency' value='USD'/>
98
+ <dxp:property name='ga:timezone' value='America/Los_Angeles'/>
99
+ <dxp:tableId>ga:12123131</dxp:tableId>
100
+ </entry>
101
+ <entry gd:etag='W/&quot;DUMNQHk_fSp7I2A9Wx5bEE4.&quot;' gd:kind='analytics#account'>
102
+ <id>http://www.google.com/analytics/feeds/accounts/ga:37685582</id>
103
+ <updated>2010-10-25T13:11:31.745-07:00</updated>
104
+ <title>The Social</title>
105
+ <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
106
+ <dxp:property name='ga:accountId' value='12312214'/>
107
+ <dxp:property name='ga:accountName' value='business.com'/>
108
+ <dxp:property name='ga:profileId' value='37685582'/>
109
+ <dxp:property name='ga:webPropertyId' value='UA-12312214-1'/>
110
+ <dxp:property name='ga:currency' value='USD'/>
111
+ <dxp:property name='ga:timezone' value='America/Los_Angeles'/>
112
+ <dxp:tableId>ga:37685582</dxp:tableId>
113
+ </entry>
114
+ <entry gd:etag='W/&quot;DE8HR3o4eCp7I2A9Wx5UF0w.&quot;' gd:kind='analytics#account'>
115
+ <id>http://www.google.com/analytics/feeds/accounts/ga:38132423</id>
116
+ <updated>2010-10-21T20:07:16.430-07:00</updated>
117
+ <title>Skyline</title>
118
+ <link rel='alternate' type='text/html' href='http://www.google.com/analytics'/>
119
+ <dxp:property name='ga:accountId' value='12312214'/>
120
+ <dxp:property name='ga:accountName' value='business.com'/>
121
+ <dxp:property name='ga:profileId' value='38132423'/>
122
+ <dxp:property name='ga:webPropertyId' value='UA-12312214-1'/>
123
+ <dxp:property name='ga:currency' value='USD'/>
124
+ <dxp:property name='ga:timezone' value='America/Los_Angeles'/>
125
+ <dxp:tableId>ga:38132423</dxp:tableId>
126
+ </entry>
127
+ </feed>