happymapper-swanandp 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/License +20 -0
  2. data/README.rdoc +55 -0
  3. data/Rakefile +35 -0
  4. data/examples/amazon.rb +34 -0
  5. data/examples/current_weather.rb +21 -0
  6. data/examples/dashed_elements.rb +20 -0
  7. data/examples/multi_street_address.rb +30 -0
  8. data/examples/post.rb +19 -0
  9. data/examples/twitter.rb +37 -0
  10. data/lib/happymapper.rb +321 -0
  11. data/lib/happymapper/attribute.rb +3 -0
  12. data/lib/happymapper/element.rb +3 -0
  13. data/lib/happymapper/item.rb +179 -0
  14. data/lib/happymapper/version.rb +3 -0
  15. data/spec/fixtures/address.xml +8 -0
  16. data/spec/fixtures/analytics.xml +61 -0
  17. data/spec/fixtures/commit.xml +52 -0
  18. data/spec/fixtures/current_weather.xml +89 -0
  19. data/spec/fixtures/family_tree.xml +7 -0
  20. data/spec/fixtures/multi_street_address.xml +9 -0
  21. data/spec/fixtures/multiple_namespaces.xml +170 -0
  22. data/spec/fixtures/nested_namespaces.xml +17 -0
  23. data/spec/fixtures/notes.xml +9 -0
  24. data/spec/fixtures/pita.xml +133 -0
  25. data/spec/fixtures/posts.xml +23 -0
  26. data/spec/fixtures/product_default_namespace.xml +10 -0
  27. data/spec/fixtures/product_no_namespace.xml +10 -0
  28. data/spec/fixtures/product_single_namespace.xml +10 -0
  29. data/spec/fixtures/radar.xml +21 -0
  30. data/spec/fixtures/raw.xml +9 -0
  31. data/spec/fixtures/statuses.xml +422 -0
  32. data/spec/happymapper_attribute_spec.rb +17 -0
  33. data/spec/happymapper_element_spec.rb +17 -0
  34. data/spec/happymapper_item_spec.rb +115 -0
  35. data/spec/happymapper_spec.rb +404 -0
  36. data/spec/happymapper_to_xml_namespaces_spec.rb +149 -0
  37. data/spec/happymapper_to_xml_spec.rb +138 -0
  38. data/spec/spec.opts +1 -0
  39. data/spec/spec_helper.rb +9 -0
  40. data/spec/support/models.rb +323 -0
  41. metadata +121 -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,179 @@
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 expath)
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.options = o
21
+
22
+ @xml_type = self.class.to_s.split('::').last.downcase
23
+ end
24
+
25
+ def constant
26
+ @constant ||= constantize(type)
27
+ end
28
+
29
+ def from_xml_node(node, namespace)
30
+ if primitive?
31
+ find(node, namespace) do |n|
32
+ if n.respond_to?(:content)
33
+ typecast(n.content)
34
+ else
35
+ typecast(n.to_s)
36
+ end
37
+ end
38
+ else
39
+ if options[:parser]
40
+ find(node, namespace) do |n|
41
+ if n.respond_to?(:content) && !options[:raw]
42
+ value = n.content
43
+ else
44
+ value = n.to_s
45
+ end
46
+
47
+ begin
48
+ constant.send(options[:parser].to_sym, value)
49
+ rescue
50
+ nil
51
+ end
52
+ end
53
+ else
54
+ constant.parse(node, options)
55
+ end
56
+ end
57
+ end
58
+
59
+ def xpath(namespace = self.namespace)
60
+ xpath = ''
61
+ xpath += './/' if options[:deep]
62
+ xpath += "#{DEFAULT_NS}:" if namespace
63
+ xpath += tag
64
+ # puts "xpath: #{xpath}"
65
+ xpath
66
+ end
67
+
68
+ def primitive?
69
+ Types.include?(constant)
70
+ end
71
+
72
+ def element?
73
+ @xml_type == 'element'
74
+ end
75
+
76
+ def attribute?
77
+ !element?
78
+ end
79
+
80
+ def method_name
81
+ @method_name ||= name.tr('-', '_')
82
+ end
83
+
84
+ def typecast(value)
85
+ return value if value.kind_of?(constant) || value.nil?
86
+ begin
87
+ if constant == String then value.to_s
88
+ elsif constant == Float then value.to_f
89
+ elsif constant == Time then Time.parse(value.to_s)
90
+ elsif constant == Date then Date.parse(value.to_s)
91
+ elsif constant == DateTime then DateTime.parse(value.to_s)
92
+ elsif constant == Boolean then ['true', 't', '1'].include?(value.to_s.downcase)
93
+ elsif constant == Integer
94
+ # ganked from datamapper
95
+ value_to_i = value.to_i
96
+ if value_to_i == 0 && value != '0'
97
+ value_to_s = value.to_s
98
+ begin
99
+ Integer(value_to_s =~ /^(\d+)/ ? $1 : value_to_s)
100
+ rescue ArgumentError
101
+ nil
102
+ end
103
+ else
104
+ value_to_i
105
+ end
106
+ else
107
+ value
108
+ end
109
+ rescue
110
+ value
111
+ end
112
+ end
113
+
114
+ private
115
+ def constantize(type)
116
+ if type.is_a?(String)
117
+ names = type.split('::')
118
+ constant = Object
119
+ names.each do |name|
120
+ constant = constant.const_defined?(name) ?
121
+ constant.const_get(name) :
122
+ constant.const_missing(name)
123
+ end
124
+ constant
125
+ else
126
+ type
127
+ end
128
+ end
129
+
130
+ def find(node, namespace, &block)
131
+ if options[:namespace] == false
132
+ namespace = nil
133
+ elsif options[:namespace]
134
+ # from an element definition
135
+ namespace = "#{DEFAULT_NS}:#{options[:namespace]}"
136
+ elsif self.namespace
137
+ # this node has a custom namespace (that is present in the doc)
138
+ namespace = "#{DEFAULT_NS}:#{self.namespace}"
139
+ end
140
+
141
+ if element?
142
+ if(options[:single].nil? || options[:single])
143
+ result = node.find_first(xpath(namespace), namespace)
144
+ else
145
+ result = node.find(xpath(namespace))
146
+ end
147
+ # puts "vfxn: #{xpath} #{result.inspect}"
148
+ if result
149
+ if(options[:single].nil? || options[:single])
150
+ value = yield(result)
151
+ else
152
+ value = []
153
+
154
+ result.each do |res|
155
+ value << yield(res)
156
+ end
157
+ end
158
+ if options[:attributes].is_a?(Hash)
159
+ result.attributes.each do |xml_attribute|
160
+ if attribute_options = options[:attributes][xml_attribute.name.to_sym]
161
+ attribute_value = Attribute.new(xml_attribute.name.to_sym, *attribute_options).from_xml_node(result, namespace)
162
+ result.instance_eval <<-EOV
163
+ def value.#{xml_attribute.name}
164
+ #{attribute_value.inspect}
165
+ end
166
+ EOV
167
+ end
168
+ end
169
+ end
170
+ value
171
+ else
172
+ nil
173
+ end
174
+ else
175
+ yield(node[tag])
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,3 @@
1
+ module HappyMapper
2
+ Version = '0.4.0'
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,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,52 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <commit>
3
+ <removed type="array">
4
+ <removed>
5
+ <filename>commands.rb</filename>
6
+ </removed>
7
+ <removed>
8
+ <filename>helpers.rb</filename>
9
+ </removed>
10
+ </removed>
11
+ <added type="array">
12
+ <added>
13
+ <filename>commands/commands.rb</filename>
14
+ </added>
15
+ <added>
16
+ <filename>commands/helpers.rb</filename>
17
+ </added>
18
+ </added>
19
+ <message>move commands.rb and helpers.rb into commands/ dir</message>
20
+ <modified type="array">
21
+ <modified>
22
+ <diff>@@ -56,7 +56,7 @@ module GitHub
23
+ end
24
+
25
+ def load(file)
26
+ - file[0] == ?/ ? super : super(BasePath + "/#{file}")
27
+ + file[0] == ?/ ? super : super(BasePath + "/commands/#{file}")
28
+ end
29
+
30
+ def debug(*messages)</diff>
31
+ <filename>lib/github.rb</filename>
32
+ </modified>
33
+ </modified>
34
+ <parents type="array">
35
+ <parent>
36
+ <id>d462d2a2e60438ded3dd9e8e6593ca4146c5a0ba</id>
37
+ </parent>
38
+ </parents>
39
+ <url>http://github.com/defunkt/github-gem/commit/c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b</url>
40
+ <author>
41
+ <name>Chris Wanstrath</name>
42
+ <email>chris@ozmm.org</email>
43
+ </author>
44
+ <id>c26d4ce9807ecf57d3f9eefe19ae64e75bcaaa8b</id>
45
+ <committed-date>2008-03-02T16:45:41-08:00</committed-date>
46
+ <authored-date>2008-03-02T16:45:41-08:00</authored-date>
47
+ <tree>28a1a1ca3e663d35ba8bf07d3f1781af71359b76</tree>
48
+ <committer>
49
+ <name>Chris Wanstrath</name>
50
+ <email>chris@ozmm.org</email>
51
+ </committer>
52
+ </commit>
@@ -0,0 +1,89 @@
1
+ <aws:weather xmlns:aws="http://www.aws.com/aws">
2
+ <aws:api version="2.0"/>
3
+ <aws:WebURL>http://weather.weatherbug.com/IN/Carmel-weather.html?ZCode=Z5546&amp;Units=0&amp;stat=MOCAR</aws:WebURL>
4
+ <aws:ob>
5
+ <aws:ob-date>
6
+ <aws:year number="2008"/>
7
+ <aws:month number="12" text="December" abbrv="Dec"/>
8
+ <aws:day number="30" text="Tuesday" abbrv="Tue"/>
9
+ <aws:hour number="4" hour-24="16"/>
10
+ <aws:minute number="18"/>
11
+ <aws:second number="01"/>
12
+ <aws:am-pm abbrv="PM"/>
13
+ <aws:time-zone offset="-5" text="Eastern Standard Time" abbrv="EST"/>
14
+ </aws:ob-date>
15
+ <aws:requested-station-id>mocar</aws:requested-station-id>
16
+ <aws:station-id>MOCAR</aws:station-id>
17
+ <aws:station>Mohawk Trail ES</aws:station>
18
+ <aws:city-state zipcode="46033">Carmel, IN</aws:city-state>
19
+ <aws:country>USA</aws:country>
20
+ <aws:latitude>39.9711111111111</aws:latitude>
21
+ <aws:longitude>-86.0938888888889</aws:longitude>
22
+ <aws:site-url>http://www1.ccs.k12.in.us/mte/home</aws:site-url>
23
+ <aws:aux-temp units="&amp;deg;F">74</aws:aux-temp>
24
+ <aws:aux-temp-rate units="&amp;deg;F">+0.0</aws:aux-temp-rate>
25
+ <aws:current-condition icon="http://deskwx.weatherbug.com/images/Forecast/icons/cond007.gif">Sunny</aws:current-condition>
26
+ <aws:dew-point units="&amp;deg;F">35</aws:dew-point>
27
+ <aws:elevation units="ft">817</aws:elevation>
28
+ <aws:feels-like units="&amp;deg;F">51</aws:feels-like>
29
+ <aws:gust-time>
30
+ <aws:year number="0001"/>
31
+ <aws:month number="1" text="January" abbrv="Jan"/>
32
+ <aws:day number="1" text="Monday" abbrv="Mon"/>
33
+ <aws:hour number="12" hour-24="00"/>
34
+ <aws:minute number="00"/>
35
+ <aws:second number="00"/>
36
+ <aws:am-pm abbrv="AM"/>
37
+ <aws:time-zone offset="-5" text="Eastern Standard Time" abbrv="EST"/>
38
+ </aws:gust-time>
39
+ <aws:gust-direction>W</aws:gust-direction>
40
+ <aws:gust-speed units="mph">25</aws:gust-speed>
41
+ <aws:humidity units="%">53</aws:humidity>
42
+ <aws:humidity-high units="%">100.0</aws:humidity-high>
43
+ <aws:humidity-low units="%">42.5</aws:humidity-low>
44
+ <aws:humidity-rate>-5.0</aws:humidity-rate>
45
+ <aws:indoor-temp units="&amp;deg;F">75</aws:indoor-temp>
46
+ <aws:indoor-temp-rate units="&amp;deg;F">+0.0</aws:indoor-temp-rate>
47
+ <aws:light>28</aws:light>
48
+ <aws:light-rate>-1.5</aws:light-rate>
49
+ <aws:moon-phase moon-phase-img="http://api.wxbug.net/images/moonphase/mphase02.gif">-10</aws:moon-phase>
50
+ <aws:pressure units="&quot;">29.71</aws:pressure>
51
+ <aws:pressure-high units="&quot;">30.18</aws:pressure-high>
52
+ <aws:pressure-low units="&quot;">29.71</aws:pressure-low>
53
+ <aws:pressure-rate units="&quot;/h">-0.04</aws:pressure-rate>
54
+ <aws:rain-month units="&quot;">6.64</aws:rain-month>
55
+ <aws:rain-rate units="&quot;/h">0.00</aws:rain-rate>
56
+ <aws:rain-rate-max units="&quot;/h">0.00</aws:rain-rate-max>
57
+ <aws:rain-today units="&quot;">0.00</aws:rain-today>
58
+ <aws:rain-year units="&quot;">53.83</aws:rain-year>
59
+ <aws:temp units="&amp;deg;F">51.8</aws:temp>
60
+ <aws:temp-high units="&amp;deg;F">52</aws:temp-high>
61
+ <aws:temp-low units="&amp;deg;F">29</aws:temp-low>
62
+ <aws:temp-rate units="&amp;deg;F/h">+2.5</aws:temp-rate>
63
+ <aws:sunrise>
64
+ <aws:year number="2008"/>
65
+ <aws:month number="12" text="December" abbrv="Dec"/>
66
+ <aws:day number="30" text="Tuesday" abbrv="Tue"/>
67
+ <aws:hour number="8" hour-24="08"/>
68
+ <aws:minute number="06"/>
69
+ <aws:second number="02"/>
70
+ <aws:am-pm abbrv="AM"/>
71
+ <aws:time-zone offset="-5" text="Eastern Standard Time" abbrv="EST"/>
72
+ </aws:sunrise>
73
+ <aws:sunset>
74
+ <aws:year number="2008"/>
75
+ <aws:month number="12" text="December" abbrv="Dec"/>
76
+ <aws:day number="30" text="Tuesday" abbrv="Tue"/>
77
+ <aws:hour number="5" hour-24="17"/>
78
+ <aws:minute number="28"/>
79
+ <aws:second number="53"/>
80
+ <aws:am-pm abbrv="PM"/>
81
+ <aws:time-zone offset="-5" text="Eastern Standard Time" abbrv="EST"/>
82
+ </aws:sunset>
83
+ <aws:wet-bulb units="&amp;deg;F">44.24</aws:wet-bulb>
84
+ <aws:wind-speed units="mph">4</aws:wind-speed>
85
+ <aws:wind-speed-avg units="mph">7</aws:wind-speed-avg>
86
+ <aws:wind-direction>SSW</aws:wind-direction>
87
+ <aws:wind-direction-avg>SW</aws:wind-direction-avg>
88
+ </aws:ob>
89
+ </aws:weather>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <familytree xmlns="http://api.familysearch.org/familytree/v1" xmlns:fsapi-v1="http://api.familysearch.org/v1" version="1.0.20071213.942" statusMessage="OK" statusCode="200">
3
+ <persons>
4
+ <person version="1199378491000" modified="2008-01-03T09:41:31-07:00" id="KWQS-BBQ">
5
+ </person>
6
+ </persons>
7
+ </familytree>
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <address>
3
+ <streetaddress>123 Smith Dr</streetaddress>
4
+ <streetaddress>Apt 31</streetaddress>
5
+ <city>Anytown</city>
6
+ <stateOrProvince>ST</stateOrProvince>
7
+ <zip>12345</zip>
8
+ <country>USA</country>
9
+ </address>
@@ -0,0 +1,170 @@
1
+ <?xml version='1.0' encoding='UTF-8'?>
2
+ <v2:TrackReply xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:v2='http://fedex.com/ws/track/v2'>
3
+ <v2:HighestSeverity>SUCCESS</v2:HighestSeverity>
4
+ <v2:Notifications>
5
+ <v2:Severity>SUCCESS</v2:Severity>
6
+ <v2:Source>trck</v2:Source>
7
+ <v2:Code>0</v2:Code>
8
+ <v2:Message>Request was successfully processed.</v2:Message>
9
+ <v2:LocalizedMessage>Request was successfully processed.</v2:LocalizedMessage>
10
+ </v2:Notifications>
11
+ <ns:TransactionDetail xmlns:ns='http://fedex.com/ws/track/v2'>
12
+ <ns:CustomerTransactionId>20090102-111321</ns:CustomerTransactionId>
13
+ </ns:TransactionDetail>
14
+ <ns:Version xmlns:ns='http://fedex.com/ws/track/v2'>
15
+ <ns:ServiceId>trck</ns:ServiceId>
16
+ <ns:Major>2</ns:Major>
17
+ <ns:Intermediate>0</ns:Intermediate>
18
+ <ns:Minor>0</ns:Minor>
19
+ </ns:Version>
20
+ <v2:DuplicateWaybill>false</v2:DuplicateWaybill>
21
+ <v2:MoreData>false</v2:MoreData>
22
+ <v2:TrackDetails>
23
+ <v2:TrackingNumber>9611018034267800045212</v2:TrackingNumber>
24
+ <v2:TrackingNumberUniqueIdentifier>120081227094248461000~034267800045212</v2:TrackingNumberUniqueIdentifier>
25
+ <v2:StatusCode>OD</v2:StatusCode>
26
+ <v2:StatusDescription>On FedEx vehicle for delivery</v2:StatusDescription>
27
+ <v2:CarrierCode>FDXG</v2:CarrierCode>
28
+ <v2:ServiceInfo>Ground-Package Returns Program-Domestic</v2:ServiceInfo>
29
+ <v2:PackageWeight>
30
+ <v2:Units>LB</v2:Units>
31
+ <v2:Value>2.6</v2:Value>
32
+ </v2:PackageWeight>
33
+ <v2:Packaging>Package</v2:Packaging>
34
+ <v2:PackageSequenceNumber>1</v2:PackageSequenceNumber>
35
+ <v2:PackageCount>1</v2:PackageCount>
36
+ <v2:OriginLocationAddress>
37
+ <v2:City>SANFORD</v2:City>
38
+ <v2:StateOrProvinceCode>FL</v2:StateOrProvinceCode>
39
+ <v2:CountryCode>US</v2:CountryCode>
40
+ <v2:Residential>false</v2:Residential>
41
+ </v2:OriginLocationAddress>
42
+ <v2:ShipTimestamp>2008-12-29T00:00:00</v2:ShipTimestamp>
43
+ <v2:EstimatedDeliveryTimestamp>2009-01-02T00:00:00</v2:EstimatedDeliveryTimestamp>
44
+ <v2:SignatureProofOfDeliveryAvailable>false</v2:SignatureProofOfDeliveryAvailable>
45
+ <v2:ProofOfDeliveryNotificationsAvailable>true</v2:ProofOfDeliveryNotificationsAvailable>
46
+ <v2:ExceptionNotificationsAvailable>true</v2:ExceptionNotificationsAvailable>
47
+ <v2:Events>
48
+ <v2:Timestamp>2009-01-02T06:00:00</v2:Timestamp>
49
+ <v2:EventType>OD</v2:EventType>
50
+ <v2:EventDescription>On FedEx vehicle for delivery</v2:EventDescription>
51
+ <v2:Address>
52
+ <v2:City>WICHITA</v2:City>
53
+ <v2:StateOrProvinceCode>KS</v2:StateOrProvinceCode>
54
+ <v2:PostalCode>67226</v2:PostalCode>
55
+ <v2:CountryCode>US</v2:CountryCode>
56
+ <v2:Residential>false</v2:Residential>
57
+ </v2:Address>
58
+ </v2:Events>
59
+ <v2:Events>
60
+ <v2:Timestamp>2009-01-02T01:17:32</v2:Timestamp>
61
+ <v2:EventType>AR</v2:EventType>
62
+ <v2:EventDescription>At local FedEx facility</v2:EventDescription>
63
+ <v2:Address>
64
+ <v2:City>WICHITA</v2:City>
65
+ <v2:StateOrProvinceCode>KS</v2:StateOrProvinceCode>
66
+ <v2:PostalCode>67226</v2:PostalCode>
67
+ <v2:CountryCode>US</v2:CountryCode>
68
+ <v2:Residential>false</v2:Residential>
69
+ </v2:Address>
70
+ </v2:Events>
71
+ <v2:Events>
72
+ <v2:Timestamp>2009-01-01T21:49:49</v2:Timestamp>
73
+ <v2:EventType>DP</v2:EventType>
74
+ <v2:EventDescription>Departed FedEx location</v2:EventDescription>
75
+ <v2:Address>
76
+ <v2:City>LENEXA</v2:City>
77
+ <v2:StateOrProvinceCode>KS</v2:StateOrProvinceCode>
78
+ <v2:PostalCode>66227</v2:PostalCode>
79
+ <v2:CountryCode>US</v2:CountryCode>
80
+ <v2:Residential>false</v2:Residential>
81
+ </v2:Address>
82
+ </v2:Events>
83
+ <v2:Events>
84
+ <v2:Timestamp>2008-12-31T16:19:00</v2:Timestamp>
85
+ <v2:EventType>AR</v2:EventType>
86
+ <v2:EventDescription>Arrived at FedEx location</v2:EventDescription>
87
+ <v2:Address>
88
+ <v2:City>LENEXA</v2:City>
89
+ <v2:StateOrProvinceCode>KS</v2:StateOrProvinceCode>
90
+ <v2:PostalCode>66227</v2:PostalCode>
91
+ <v2:CountryCode>US</v2:CountryCode>
92
+ <v2:Residential>false</v2:Residential>
93
+ </v2:Address>
94
+ </v2:Events>
95
+ <v2:Events>
96
+ <v2:Timestamp>2008-12-30T11:01:23</v2:Timestamp>
97
+ <v2:EventType>DP</v2:EventType>
98
+ <v2:EventDescription>Departed FedEx location</v2:EventDescription>
99
+ <v2:Address>
100
+ <v2:City>ORLANDO</v2:City>
101
+ <v2:StateOrProvinceCode>FL</v2:StateOrProvinceCode>
102
+ <v2:PostalCode>32809</v2:PostalCode>
103
+ <v2:CountryCode>US</v2:CountryCode>
104
+ <v2:Residential>false</v2:Residential>
105
+ </v2:Address>
106
+ </v2:Events>
107
+ <v2:Events>
108
+ <v2:Timestamp>2008-12-30T05:00:00</v2:Timestamp>
109
+ <v2:EventType>AR</v2:EventType>
110
+ <v2:EventDescription>Arrived at FedEx location</v2:EventDescription>
111
+ <v2:Address>
112
+ <v2:City>ORLANDO</v2:City>
113
+ <v2:StateOrProvinceCode>FL</v2:StateOrProvinceCode>
114
+ <v2:PostalCode>32809</v2:PostalCode>
115
+ <v2:CountryCode>US</v2:CountryCode>
116
+ <v2:Residential>false</v2:Residential>
117
+ </v2:Address>
118
+ </v2:Events>
119
+ <v2:Events>
120
+ <v2:Timestamp>2008-12-30T03:16:33</v2:Timestamp>
121
+ <v2:EventType>DP</v2:EventType>
122
+ <v2:EventDescription>Left FedEx origin facility</v2:EventDescription>
123
+ <v2:Address>
124
+ <v2:City>SANFORD</v2:City>
125
+ <v2:StateOrProvinceCode>FL</v2:StateOrProvinceCode>
126
+ <v2:PostalCode>32771</v2:PostalCode>
127
+ <v2:CountryCode>US</v2:CountryCode>
128
+ <v2:Residential>false</v2:Residential>
129
+ </v2:Address>
130
+ </v2:Events>
131
+ <v2:Events>
132
+ <v2:Timestamp>2008-12-29T22:46:00</v2:Timestamp>
133
+ <v2:EventType>AR</v2:EventType>
134
+ <v2:EventDescription>Arrived at FedEx location</v2:EventDescription>
135
+ <v2:Address>
136
+ <v2:City>SANFORD</v2:City>
137
+ <v2:StateOrProvinceCode>FL</v2:StateOrProvinceCode>
138
+ <v2:PostalCode>32771</v2:PostalCode>
139
+ <v2:CountryCode>US</v2:CountryCode>
140
+ <v2:Residential>false</v2:Residential>
141
+ </v2:Address>
142
+ </v2:Events>
143
+ <v2:Events>
144
+ <v2:Timestamp>2008-12-29T17:12:00</v2:Timestamp>
145
+ <v2:EventType>PU</v2:EventType>
146
+ <v2:EventDescription>Picked up</v2:EventDescription>
147
+ <v2:Address>
148
+ <v2:City>SANFORD</v2:City>
149
+ <v2:StateOrProvinceCode>FL</v2:StateOrProvinceCode>
150
+ <v2:PostalCode>32771</v2:PostalCode>
151
+ <v2:CountryCode>US</v2:CountryCode>
152
+ <v2:Residential>false</v2:Residential>
153
+ </v2:Address>
154
+ </v2:Events>
155
+ <v2:Events>
156
+ <v2:Timestamp>2008-12-27T09:40:00</v2:Timestamp>
157
+ <v2:EventType>IP</v2:EventType>
158
+ <v2:EventDescription>In FedEx possession</v2:EventDescription>
159
+ <v2:StatusExceptionCode>084</v2:StatusExceptionCode>
160
+ <v2:StatusExceptionDescription>Tendered at FedEx location</v2:StatusExceptionDescription>
161
+ <v2:Address>
162
+ <v2:City>LONGWOOD</v2:City>
163
+ <v2:StateOrProvinceCode>FL</v2:StateOrProvinceCode>
164
+ <v2:PostalCode>327506398</v2:PostalCode>
165
+ <v2:CountryCode>US</v2:CountryCode>
166
+ <v2:Residential>false</v2:Residential>
167
+ </v2:Address>
168
+ </v2:Events>
169
+ </v2:TrackDetails>
170
+ </v2:TrackReply>