eeml 0.0.34 → 0.0.35

Sign up to get free protection for your applications and to get access to all the features.
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