eeml 0.0.34 → 0.0.35

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.
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ .rvmrc
2
+ pkg
3
+ coverage/
4
+ doc
5
+ eeml.gemspec
6
+ client_config.yml
7
+ coverage/
8
+ .*.swp
9
+ gem_deps_manual/
data/README CHANGED
@@ -4,8 +4,10 @@
4
4
 
5
5
  == DESCRIPTION:
6
6
 
7
- Library for simplifying the creation and manipulation of EEML documents, primarily intended for use with pachube.com. Provides parsing of EEML documents into
8
- ruby objects that can be used programmatically. Also provides parsing and output of the JSON format used by pachube.com.
7
+ Library for simplifying the creation and manipulation of EEML documents,
8
+ primarily intended for use with pachube.com. Provides parsing of EEML documents
9
+ into ruby objects that can be used programmatically. Also provides parsing and
10
+ output of the JSON format used by pachube.com.
9
11
 
10
12
  == USAGE
11
13
 
data/lib/eeml.rb CHANGED
@@ -16,7 +16,7 @@ require 'time'
16
16
  module Eeml
17
17
 
18
18
  # library version number
19
- VERSION = '0.0.34'
19
+ VERSION = '0.0.35'
20
20
 
21
21
  # TODO: put in some configuration file, not here
22
22
  LOCAL_EEML_SCHEMA_LOCATION = 'schemas/eeml/005.xsd'
@@ -33,6 +33,14 @@ module Eeml
33
33
  :schema_location => 'http://www.eeml.org/xsd/0.5.1 http://www.eeml.org/xsd/0.5.1/0.5.1.xsd'
34
34
  }
35
35
 
36
+ # This is NEWER than version 5
37
+ EEML["0.5.2"] =
38
+ {
39
+ :href => 'http://www.eeml.org/xsd/0.5.2',
40
+ :versions => '0.5.2',
41
+ :schema_location => 'http://www.eeml.org/xsd/0.5.2 http://www.eeml.org/xsd/0.5.2/0.5.2.xsd'
42
+ }
43
+
36
44
  JSON_API["0.6-alpha"] =
37
45
  {
38
46
  :versions => ['0.6', '0.6-alpha']
@@ -93,12 +93,22 @@ module Eeml
93
93
  end
94
94
  end
95
95
 
96
+ class Owner
97
+ attr_accessor :login, :url
98
+
99
+ def initialize(options = {})
100
+ @login = options[:login]
101
+ @url = options[:url]
102
+ end
103
+ end
104
+
96
105
  # This class represents the main point of entry to this library. In general we will be creating instances of this class, either
97
106
  # by manually specifying the parameters, or probably more commonly, by passing in either an EEML or JSON formatted string which
98
107
  # will be parsed to initialize the object.
99
108
  class Environment
100
109
  attr_accessor :identifier, :updated, :creator
101
110
  attr_accessor :title, :description, :feed_url, :website, :email, :icon, :status
111
+ attr_accessor :owner
102
112
  attr_accessor :location
103
113
  attr_accessor :csv_version
104
114
  attr_accessor :datastreams
@@ -2,6 +2,7 @@ require 'eeml/csv_parser_v1'
2
2
  require 'eeml/csv_parser_v2'
3
3
  require 'eeml/libxml_eeml_parser_v005'
4
4
  require 'eeml/libxml_eeml_parser_v051'
5
+ require 'eeml/libxml_eeml_parser_v052'
5
6
  require 'eeml/json_environment_parser_v005'
6
7
  require 'eeml/json_environment_parser_v006'
7
8
  require 'eeml/json_environment_parser_v100'
@@ -16,6 +17,8 @@ module Eeml
16
17
  xml = XML::Parser.string(xml_str).parse
17
18
  if xml.root.namespaces.default.to_s == Constants::EEML['0.5.1'][:href]
18
19
  parser = LibXMLEemlParserV051.new
20
+ elsif xml.root.namespaces.default.to_s == Constants::EEML['0.5.2'][:href]
21
+ parser = LibXMLEemlParserV052.new
19
22
  else
20
23
  parser = LibXMLEemlParserV005.new
21
24
  end
@@ -18,6 +18,8 @@ module Eeml
18
18
 
19
19
  env.tags = env_hash['tags'] unless env_hash['tags'].nil?
20
20
 
21
+ env.owner = buildOwner(env_hash)
22
+
21
23
  env.location = buildLocation(env_hash)
22
24
 
23
25
  env.add_datastreams(buildDatastreams(env_hash))
@@ -32,6 +34,13 @@ module Eeml
32
34
 
33
35
  private
34
36
 
37
+ def buildOwner(env_hash)
38
+ owner_hash = env_hash["owner"]
39
+ return if owner_hash.nil?
40
+ Owner.new(:login => owner_hash["login"],
41
+ :url => owner_hash["url"])
42
+ end
43
+
35
44
  def buildLocation(env_hash)
36
45
  location_hash = env_hash["location"]
37
46
  return if location_hash.nil?
@@ -0,0 +1,232 @@
1
+ require "parsedate.rb"
2
+ module Eeml
3
+ #a parser for xml eeml v052, implemented with LibXML
4
+ class LibXMLEemlParserV052 # :nodoc:
5
+ include LibXML
6
+ include Exceptions
7
+
8
+ @@eeml_version = Constants::EEML['0.5.2']
9
+ #main method
10
+
11
+ #take an xml string, and create an Environment from it.
12
+ #If an optional environment is given, that will be populated (overwritten) instead of a new environment.
13
+ def make_environment_from_xml(xml_str, given_environment = nil)
14
+ doc = parse_xml(xml_str)
15
+ raise MissingNamespace if doc.root.namespaces.namespace.blank?
16
+ env = given_environment || Environment.new
17
+ #TODO: what has to be reset in a given environment before passing it for re-population?
18
+ return extract_environment_from_doc(doc, env)
19
+ end
20
+
21
+ #take an xml string containing zero or more environment nodes, and create an array of Environment objects from it.
22
+ def make_environments_from_xml(xml_str)
23
+ doc = parse_xml(xml_str)
24
+ raise MissingNamespace if doc.root.namespaces.namespace.blank?
25
+ return extract_environments_from_doc(doc)
26
+ end
27
+
28
+ protected
29
+
30
+ def parse_xml(xml_str)
31
+ errors = []
32
+ #http://libxml.rubyforge.org/rdoc/classes/LibXML/XML/Error.html
33
+ #TODO: is the error handler set up per thread? (XML::Error.set_handler)
34
+ XML::Error.set_handler { |error| errors << error }
35
+
36
+ #TODO: performance - is this expensive?
37
+ #TODO: are these configurations per-thread? If they're global (e.g. class variables) then we shouldn't be setting them here.
38
+ XML.default_line_numbers=true
39
+
40
+ parser = XML::Parser.string(strip_content(xml_str))
41
+ begin
42
+ doc = parser.parse
43
+ rescue XML::Error => e
44
+ #note: errors var available here, too.
45
+ raise BadXML, "Malformed xml: #{e.class}: #{e}", e.backtrace
46
+ end
47
+ #validation?
48
+ # seems we have to recreate our XML::Schema object on each invocation
49
+ # else libxml segfaults very quickly
50
+ #doc.validate_schema(XML::Schema.from_string(IO.read(LOCAL_EEML5_SCHEMA_LOCATION)))
51
+ return doc
52
+ end
53
+
54
+ #multiple (zero or more)
55
+ def extract_environments_from_doc(doc)
56
+ env_nodes = doc.find('x:environment', "x:#{@@eeml_version[:href]}")
57
+ return env_nodes.map{|env_node| new_env = Environment.new; extract_environment_from_node(env_node, new_env)}
58
+ end
59
+
60
+ #single, mandatory
61
+ def extract_environment_from_doc(doc, env_to_populate)
62
+ env_node = find_first_node_or_fail(doc, 'x:environment', 'environment', "x:#{@@eeml_version[:href]}")
63
+ return extract_environment_from_node(env_node, env_to_populate)
64
+ end
65
+
66
+ #single, from node (everyone uses this to get the work done)
67
+ def extract_environment_from_node(env_node, env_to_populate)
68
+ env = env_to_populate
69
+ env.identifier = env_node['id']
70
+ env.updated = Time.parse(env_node['updated']) if !env_node['updated'].nil?
71
+
72
+ env.creator = env_node['creator']
73
+
74
+ env.title = optional_content(env_node, 'x:title', 'title', "x:#{@@eeml_version[:href]}")
75
+ env.feed_url = optional_content(env_node, 'x:feed', 'feed', "x:#{@@eeml_version[:href]}")
76
+ env.description = optional_content(env_node, 'x:description', 'description', "x:#{@@eeml_version[:href]}")
77
+ env.website = optional_content(env_node, 'x:website', 'website', "x:#{@@eeml_version[:href]}")
78
+ env.status = optional_content(env_node, 'x:status', 'status', "x:#{@@eeml_version[:href]}")
79
+ env.email = optional_content(env_node, 'x:email', 'email', "x:#{@@eeml_version[:href]}")
80
+ env.icon = optional_content(env_node, 'x:icon', 'icon', "x:#{@@eeml_version[:href]}")
81
+ env.private = (optional_content(env_node, 'x:private', 'private', "x:#{@@eeml_version[:href]}") == "true")
82
+
83
+ owner_node = env_node.find_first('x:owner', "x:#{@@eeml_version[:href]}")
84
+ env.owner = extractOwner(owner_node) if owner_node
85
+
86
+ #find_first_node_or_fail(env_node, 'x:location', 'location')
87
+ loc_node = env_node.find_first('x:location', "x:#{@@eeml_version[:href]}")
88
+ env.location = extractLocation(loc_node) if loc_node
89
+
90
+ env_node.find('x:tag', "x:#{@@eeml_version[:href]}").each do |tag_node|
91
+ env.tags << tag_node.content.strip
92
+ end
93
+
94
+ datastream_nodes = env_node.find('x:data', "x:#{@@eeml_version[:href]}")
95
+ # raise NoDataStreams.new, "no datastreams found" if datastream_nodes.empty?
96
+ env.add_datastreams(extractDataStreams(datastream_nodes)) unless datastream_nodes.empty?
97
+
98
+ return env
99
+ end
100
+
101
+ def extractOwner(node)
102
+ #<owner>
103
+ # <login>bob</login>
104
+ # <url>http://pachube.com/users/bob</url>
105
+ #</owner>
106
+ raise "given nil node" if node.nil?
107
+ owner = Owner.new
108
+ owner.login = optional_content(node, 'x:login', 'login', "x:#{@eeml_version[:href]}")
109
+ owner.url = optional_content(node, 'x:url', 'url', "x:#{@eeml_version[:href]}")
110
+ return owner
111
+ end
112
+
113
+ def extractLocation(node)
114
+ #<location domain="physical" exposure="outdoor" disposition="mobile">
115
+ # <lat>50.1</lat>
116
+ # <lon>48.7</lon>
117
+ # <ele>1.34</ele>
118
+ #</location>
119
+ raise "given nil node" if node.nil?
120
+ loc = Location.new
121
+ loc.domain = node['domain']
122
+ loc.disposition = node['disposition']
123
+ loc.exposure = node['exposure']
124
+ loc.name = optional_content(node, 'x:name', 'name', "x:#{@@eeml_version[:href]}")
125
+ loc.latitude = optional_content(node, 'x:lat', 'lat', "x:#{@@eeml_version[:href]}")
126
+ loc.longitude = optional_content(node, 'x:lon', 'lon', "x:#{@@eeml_version[:href]}")
127
+ loc.elevation = optional_content(node, 'x:ele', 'ele', "x:#{@@eeml_version[:href]}")
128
+ return loc
129
+ end
130
+
131
+ #return an array (TODO: or a hash?) of DataStream objects from the given list of data nodes
132
+ def extractDataStreams(nodes)
133
+ #<data id="blah1">...</data><data id="blah2">...</data>
134
+ dataStreams = []
135
+ nodes.each do |node|
136
+ dataStreams << extractDataStream(node)
137
+ end
138
+ return dataStreams
139
+ end
140
+
141
+ #builds and returns a detailed exception of the given class, for problems concerning the given node (or its missing children)
142
+ #details include node's name and line number (zero if not available)
143
+ def exception_for_node(node, exception_class, message)
144
+ ex = exception_class.new(message)
145
+ ex.line_num = node.line_num
146
+ ex.node_name = node_name_or_root(node)
147
+ return ex
148
+ end
149
+
150
+
151
+ def extractDataStream(node)
152
+ #<data id="0">
153
+ #<tag>some_tag</tag>
154
+ #<tag>another_tag</tag>
155
+ #<current_value>0</current_value>
156
+ #<min_value>0.0</min_value>
157
+ #<max_value>1022.0</max_value>
158
+ #<unit symbol="C" type="basicSI">Celsius</unit>
159
+ #</data>
160
+ data = DataStream.new
161
+ raise MissingAttribute.new(node.name, 'id') if node['id'].nil?
162
+ data.identifier = node['id']
163
+ node.find('x:tag', "x:#{@@eeml_version[:href]}").each do |tag_node|
164
+ data.tags << tag_node.content.strip
165
+ end
166
+
167
+ value_nodes = node.find('x:current_value', "x:#{@@eeml_version[:href]}")
168
+ # raise exception_for_node(node, DataMissingValue, "Data node is missing current_value node.") if value_nodes.empty?
169
+ raise exception_for_node(node, DataHasMultipleValues, "Data node has multiple 'value' nodes.") if value_nodes.size > 1
170
+
171
+ value_node = value_nodes.first
172
+
173
+ max_value_node = node.find_first('x:max_value', "x:#{@@eeml_version[:href]}")
174
+ min_value_node = node.find_first('x:min_value', "x:#{@@eeml_version[:href]}")
175
+
176
+ value = Value.new
177
+ value.min_value = min_value_node.content if min_value_node
178
+ value.max_value = max_value_node.content if max_value_node
179
+ if value_node
180
+ value.value = value_node.content.strip
181
+ value.recorded_at = value_node['at'] unless value_node['at'].blank?
182
+ end
183
+
184
+ data.add_value(value)
185
+
186
+ unit_nodes = node.find('x:unit', "x:#{@@eeml_version[:href]}")
187
+ raise exception_for_node(node, DataHasMultipleUnits, "Data node has multiple 'unit' nodes.") if unit_nodes.size > 1
188
+
189
+ unit_node = unit_nodes.first
190
+ unless unit_node.nil?
191
+ data.unit_symbol = unit_node['symbol']
192
+ data.unit_type = unit_node['type']
193
+ data.unit_value = unit_node.content.strip
194
+ end
195
+
196
+ return data
197
+ end
198
+
199
+ #Helpers ------------------------------------------------------------------
200
+ #Consider mixing these in to the libxml parser for more readable code
201
+
202
+ #raises MissingNode if the node isn't there
203
+ def mandatory_content(base_node, xpath, description, nslist = nil)
204
+ node = base_node.find_first(xpath, nslist)
205
+ raise(MissingNode.new(node_name_or_root(base_node), description, xpath)) if node.nil?
206
+ return node.content
207
+ end
208
+
209
+ #returns the node's content, or the given default if the node isn't there (default itself defaults to nil)
210
+ #description isn't used, but keeps our signature same as mandatory_content(), up to that point.
211
+ def optional_content(base_node, xpath, description, nslist = nil, default = nil)
212
+ node = base_node.find_first(xpath, nslist)
213
+ return node.nil? ? default : node.content
214
+ end
215
+
216
+
217
+ #get the name of the given node if it is a node, or 'root' if it is a doc.
218
+ #for use only for error messages
219
+ def node_name_or_root(node)
220
+ node.respond_to?(:name) ? node.name : 'root'
221
+ end
222
+
223
+ def find_first_node_or_fail(base_node, xpath, description, nslist = nil)
224
+ node = base_node.find_first(xpath, nslist)
225
+ raise(MissingNode.new(node_name_or_root(base_node), description, xpath)) if node.nil?
226
+ return node
227
+ end
228
+
229
+ end
230
+
231
+ end
232
+
@@ -0,0 +1,167 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <xsd:schema xmlns="http://www.eeml.org/xsd/0.5.2" elementFormDefault="qualified" targetNamespace="http://www.eeml.org/xsd/0.5.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3
+ <xsd:element name="eeml">
4
+ <xsd:complexType>
5
+ <xsd:choice>
6
+ <xsd:element maxOccurs="unbounded" name="environment">
7
+ <xsd:complexType>
8
+ <xsd:sequence>
9
+ <xsd:element minOccurs="0" name="title" type="xsd:string" />
10
+ <xsd:element minOccurs="0" name="feed" type="xsd:anyURI" />
11
+ <xsd:element minOccurs="0" name="status">
12
+ <xsd:simpleType>
13
+ <xsd:restriction base="xsd:string">
14
+ <xsd:enumeration value="frozen" />
15
+ <xsd:enumeration value="live" />
16
+ </xsd:restriction>
17
+ </xsd:simpleType>
18
+ </xsd:element>
19
+ <xsd:element minOccurs="0" name="private">
20
+ <xsd:simpleType>
21
+ <xsd:restriction base="xsd:string">
22
+ <xsd:enumeration value="true" />
23
+ <xsd:enumeration value="false" />
24
+ </xsd:restriction>
25
+ </xsd:simpleType>
26
+ </xsd:element>
27
+ <xsd:element minOccurs="0" name="description" type="xsd:string" />
28
+ <xsd:element minOccurs="0" name="icon" type="xsd:anyURI" />
29
+ <xsd:element minOccurs="0" name="website" type="xsd:anyURI" />
30
+ <xsd:element minOccurs="0" name="email" type="xsd:string" />
31
+ <xsd:element minOccurs="0" maxOccurs="unbounded" name="tag" type="xsd:string" />
32
+ <xsd:element minOccurs="0" name="owner">
33
+ <xsd:complexType>
34
+ <xsd:sequence>
35
+ <xsd:element minOccurs="0" name="login" type="xsd:string" />
36
+ <xsd:element minOccurs="0" name="url" type="xsd:anyURI" />
37
+ </xsd:sequence>
38
+ </xsd:complexType>
39
+ </xsd:element>
40
+ <xsd:element minOccurs="0" name="location">
41
+ <xsd:complexType>
42
+ <xsd:sequence>
43
+ <xsd:element minOccurs="0" name="name" type="xsd:string" />
44
+ <xsd:element name="lat">
45
+ <xsd:simpleType>
46
+ <xsd:restriction base="xsd:double">
47
+ <xsd:minInclusive value="-90" />
48
+ <xsd:maxInclusive value="90" />
49
+ </xsd:restriction>
50
+ </xsd:simpleType>
51
+ </xsd:element>
52
+ <xsd:element name="lon">
53
+ <xsd:simpleType>
54
+ <xsd:restriction base="xsd:double">
55
+ <xsd:minInclusive value="-180" />
56
+ <xsd:maxInclusive value="180" />
57
+ </xsd:restriction>
58
+ </xsd:simpleType>
59
+ </xsd:element>
60
+ <xsd:element minOccurs="0" maxOccurs="1" name="ele" type="xsd:double" />
61
+ </xsd:sequence>
62
+ <xsd:attribute name="exposure" use="optional">
63
+ <xsd:simpleType>
64
+ <xsd:restriction base="xsd:string">
65
+ <xsd:enumeration value="indoor" />
66
+ <xsd:enumeration value="outdoor" />
67
+ </xsd:restriction>
68
+ </xsd:simpleType>
69
+ </xsd:attribute>
70
+ <xsd:attribute name="domain" use="required">
71
+ <xsd:simpleType>
72
+ <xsd:restriction base="xsd:string">
73
+ <xsd:enumeration value="physical" />
74
+ <xsd:enumeration value="virtual" />
75
+ </xsd:restriction>
76
+ </xsd:simpleType>
77
+ </xsd:attribute>
78
+ <xsd:attribute name="disposition" use="optional">
79
+ <xsd:simpleType>
80
+ <xsd:restriction base="xsd:string">
81
+ <xsd:enumeration value="fixed" />
82
+ <xsd:enumeration value="mobile" />
83
+ </xsd:restriction>
84
+ </xsd:simpleType>
85
+ </xsd:attribute>
86
+ </xsd:complexType>
87
+ </xsd:element>
88
+ <xsd:element minOccurs="1" maxOccurs="unbounded" name="data">
89
+ <xsd:complexType>
90
+ <xsd:sequence>
91
+ <xsd:element minOccurs="0" maxOccurs="unbounded" name="tag" type="xsd:string" />
92
+ <xsd:element minOccurs="0" maxOccurs="1" name="current_value">
93
+ <xsd:complexType>
94
+ <xsd:simpleContent>
95
+ <xsd:extension base="xsd:string">
96
+ <xsd:attribute name="at" type="xsd:dateTime" use="optional" />
97
+ </xsd:extension>
98
+ </xsd:simpleContent>
99
+ </xsd:complexType>
100
+ </xsd:element>
101
+ <xsd:element minOccurs="0" maxOccurs="1" name="max_value" type="xsd:string" />
102
+ <xsd:element minOccurs="0" maxOccurs="1" name="min_value" type="xsd:string" />
103
+ <xsd:element minOccurs="0" maxOccurs="1" name="datapoints">
104
+ <xsd:complexType>
105
+ <xsd:sequence>
106
+ <xsd:element minOccurs="0" maxOccurs="unbounded" name="value">
107
+ <xsd:complexType>
108
+ <xsd:simpleContent>
109
+ <xsd:extension base="xsd:string">
110
+ <xsd:attribute name="at" type="xsd:dateTime" use="optional" />
111
+ </xsd:extension>
112
+ </xsd:simpleContent>
113
+ </xsd:complexType>
114
+ </xsd:element>
115
+ </xsd:sequence>
116
+ </xsd:complexType>
117
+ </xsd:element>
118
+ <xsd:element minOccurs="0" maxOccurs="1" name="unit">
119
+ <xsd:complexType>
120
+ <xsd:simpleContent>
121
+ <xsd:extension base="xsd:string">
122
+ <xsd:attribute name="symbol" type="xsd:string" use="optional">
123
+ </xsd:attribute>
124
+ <xsd:attribute name="type" use="optional">
125
+ <xsd:simpleType>
126
+ <xsd:restriction base="xsd:string">
127
+ <xsd:enumeration value="basicSI" />
128
+ <xsd:enumeration value="derivedSI" />
129
+ <xsd:enumeration value="conversionBasedUnits" />
130
+ <xsd:enumeration value="derivedUnits" />
131
+ <xsd:enumeration value="contextDependentUnits" />
132
+ </xsd:restriction>
133
+ </xsd:simpleType>
134
+ </xsd:attribute>
135
+ </xsd:extension>
136
+ </xsd:simpleContent>
137
+ </xsd:complexType>
138
+ </xsd:element>
139
+ </xsd:sequence>
140
+ <xsd:attribute name="id" type="xsd:nonNegativeInteger" use="required" />
141
+ </xsd:complexType>
142
+ </xsd:element>
143
+ </xsd:sequence>
144
+ <xsd:attribute name="updated" use="optional">
145
+ <xsd:simpleType>
146
+ <xsd:restriction base="xsd:dateTime" />
147
+ </xsd:simpleType>
148
+ </xsd:attribute>
149
+ <xsd:attribute name="creator" use="optional">
150
+ <xsd:simpleType>
151
+ <xsd:restriction base="xsd:string" />
152
+ </xsd:simpleType>
153
+ </xsd:attribute>
154
+ <xsd:attribute name="id" type="xsd:nonNegativeInteger" use="optional" />
155
+ </xsd:complexType>
156
+ </xsd:element>
157
+ </xsd:choice>
158
+ <xsd:attribute name="version" use="optional">
159
+ <xsd:simpleType>
160
+ <xsd:restriction base="xsd:string">
161
+ <xsd:enumeration value="0.5.1" />
162
+ </xsd:restriction>
163
+ </xsd:simpleType>
164
+ </xsd:attribute>
165
+ </xsd:complexType>
166
+ </xsd:element>
167
+ </xsd:schema>
@@ -0,0 +1,8 @@
1
+ <eeml xmlns="http://www.eeml.org/xsd/0.5.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="0.5.2" xsi:schemaLocation="http://www.eeml.org/xsd/0.5.2 http://www.eeml.org/xsd/0.5.2/0.5.2.xsd">
2
+ <environment>
3
+ <title>Pachube Office environment</title>
4
+ <data id="0" />
5
+ <data id="1" />
6
+ </environment>
7
+ </eeml>
8
+
@@ -18,7 +18,7 @@ class TestEnvironment < Test::Unit::TestCase
18
18
  end
19
19
  end
20
20
 
21
- # Create an object from an eeml document
21
+ # Create an object from an eeml document
22
22
  test 'creating Env obj - attrs' do
23
23
  env = create_env_from_xml_file_one
24
24
 
@@ -36,6 +36,13 @@ class TestEnvironment < Test::Unit::TestCase
36
36
  assert_equal('http://example.com/creator/', env.creator)
37
37
  end
38
38
 
39
+ test "creating Env object from some 0.5.2 eeml" do
40
+ env = create_env_from_eeml_052
41
+
42
+ # simple text nodes available
43
+ assert_equal("Pachube Office environment", env.title)
44
+ end
45
+
39
46
  test 'location parses ok' do
40
47
  env = create_env_from_xml_file_one
41
48
 
@@ -764,4 +771,8 @@ CSV
764
771
  return nil if json.nil?
765
772
  json.gsub(/","/, '"' + "\n" + '"').sort
766
773
  end
774
+
775
+ def create_env_from_eeml_052
776
+ return create_env_from_xml_file("environment_minimal_052.xml")
777
+ end
767
778
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eeml
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 89
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 34
9
- version: 0.0.34
9
+ - 35
10
+ version: 0.0.35
10
11
  platform: ruby
11
12
  authors:
12
13
  - Neill Bogie
@@ -17,16 +18,18 @@ autorequire:
17
18
  bindir: bin
18
19
  cert_chain: []
19
20
 
20
- date: 2011-02-15 00:00:00 +00:00
21
+ date: 2011-02-24 00:00:00 +00:00
21
22
  default_executable:
22
23
  dependencies:
23
24
  - !ruby/object:Gem::Dependency
24
25
  name: libxml-ruby
25
26
  prerelease: false
26
27
  requirement: &id001 !ruby/object:Gem::Requirement
28
+ none: false
27
29
  requirements:
28
30
  - - ">="
29
31
  - !ruby/object:Gem::Version
32
+ hash: 21
30
33
  segments:
31
34
  - 1
32
35
  - 1
@@ -38,9 +41,11 @@ dependencies:
38
41
  name: yajl-ruby
39
42
  prerelease: false
40
43
  requirement: &id002 !ruby/object:Gem::Requirement
44
+ none: false
41
45
  requirements:
42
46
  - - ">="
43
47
  - !ruby/object:Gem::Version
48
+ hash: 19
44
49
  segments:
45
50
  - 0
46
51
  - 7
@@ -52,9 +57,11 @@ dependencies:
52
57
  name: lightcsv
53
58
  prerelease: false
54
59
  requirement: &id003 !ruby/object:Gem::Requirement
60
+ none: false
55
61
  requirements:
56
62
  - - ">="
57
63
  - !ruby/object:Gem::Version
64
+ hash: 19
58
65
  segments:
59
66
  - 0
60
67
  - 2
@@ -72,6 +79,7 @@ extra_rdoc_files:
72
79
  - LICENSE
73
80
  - README
74
81
  files:
82
+ - .gitignore
75
83
  - CHANGELOG
76
84
  - LICENSE
77
85
  - Manifest
@@ -93,7 +101,9 @@ files:
93
101
  - lib/eeml/json_environment_parser_v100.rb
94
102
  - lib/eeml/libxml_eeml_parser_v005.rb
95
103
  - lib/eeml/libxml_eeml_parser_v051.rb
104
+ - lib/eeml/libxml_eeml_parser_v052.rb
96
105
  - schemas/eeml/0.5.1.xsd
106
+ - schemas/eeml/0.5.2.xsd
97
107
  - schemas/eeml/005.xsd
98
108
  - test/data/.gitignore
99
109
  - test/data/complete_namespaced.xml
@@ -112,6 +122,7 @@ files:
112
122
  - test/data/doc_2_expected.json
113
123
  - test/data/eeml_datastream_051.xml
114
124
  - test/data/environment_minimal_051.xml
125
+ - test/data/environment_minimal_052.xml
115
126
  - test/data/environment_tags.json
116
127
  - test/data/environment_tags.xml
117
128
  - test/data/list.xml
@@ -130,36 +141,40 @@ homepage:
130
141
  licenses: []
131
142
 
132
143
  post_install_message:
133
- rdoc_options: []
134
-
144
+ rdoc_options:
145
+ - --charset=UTF-8
135
146
  require_paths:
136
147
  - lib
137
148
  required_ruby_version: !ruby/object:Gem::Requirement
149
+ none: false
138
150
  requirements:
139
151
  - - ">="
140
152
  - !ruby/object:Gem::Version
153
+ hash: 3
141
154
  segments:
142
155
  - 0
143
156
  version: "0"
144
157
  required_rubygems_version: !ruby/object:Gem::Requirement
158
+ none: false
145
159
  requirements:
146
160
  - - ">="
147
161
  - !ruby/object:Gem::Version
162
+ hash: 3
148
163
  segments:
149
164
  - 0
150
165
  version: "0"
151
166
  requirements: []
152
167
 
153
168
  rubyforge_project:
154
- rubygems_version: 1.3.6
169
+ rubygems_version: 1.3.7
155
170
  signing_key:
156
171
  specification_version: 3
157
172
  summary: Simple little library for programmatically manipulating EEML documents.
158
173
  test_files:
159
- - test/libxml_test_helper.rb
160
- - test/test_csv_parser_v1.rb
174
+ - test/test_libxml_eeml_parser_v005.rb
175
+ - test/test_libxml_test_helper.rb
161
176
  - test/test_csv_parser_v2.rb
177
+ - test/test_csv_parser_v1.rb
162
178
  - test/test_environment.rb
179
+ - test/libxml_test_helper.rb
163
180
  - test/test_helper.rb
164
- - test/test_libxml_eeml_parser_v005.rb
165
- - test/test_libxml_test_helper.rb