shibkit-meta_meta 0.2.2
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/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +21 -0
- data/Gemfile.lock +52 -0
- data/Icon.png +0 -0
- data/LICENSE.txt +177 -0
- data/README.md +789 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/examples/biggest_entity_id.rb +4 -0
- data/lib/shibkit/meta_meta.rb +600 -0
- data/lib/shibkit/meta_meta/attribute.rb +73 -0
- data/lib/shibkit/meta_meta/config.rb +463 -0
- data/lib/shibkit/meta_meta/contact.rb +85 -0
- data/lib/shibkit/meta_meta/data/default_metadata/example_federation_metadata.xml +168 -0
- data/lib/shibkit/meta_meta/data/default_metadata/local_metadata.xml +66 -0
- data/lib/shibkit/meta_meta/data/default_metadata/uncommon_federation_metadata.xml +115 -0
- data/lib/shibkit/meta_meta/data/default_metadata_cache.yml +166 -0
- data/lib/shibkit/meta_meta/data/dev_sources.yml +86 -0
- data/lib/shibkit/meta_meta/data/real_sources.yml +163 -0
- data/lib/shibkit/meta_meta/entity.rb +219 -0
- data/lib/shibkit/meta_meta/federation.rb +161 -0
- data/lib/shibkit/meta_meta/idp.rb +81 -0
- data/lib/shibkit/meta_meta/logo.rb +216 -0
- data/lib/shibkit/meta_meta/metadata_item.rb +244 -0
- data/lib/shibkit/meta_meta/mixin/cached_downloads.rb +127 -0
- data/lib/shibkit/meta_meta/mixin/xpath_chores.rb +111 -0
- data/lib/shibkit/meta_meta/organisation.rb +73 -0
- data/lib/shibkit/meta_meta/provider.rb +195 -0
- data/lib/shibkit/meta_meta/provisioning/base.rb +33 -0
- data/lib/shibkit/meta_meta/requested_attribute.rb +29 -0
- data/lib/shibkit/meta_meta/service.rb +94 -0
- data/lib/shibkit/meta_meta/source.rb +558 -0
- data/lib/shibkit/meta_meta/sp.rb +79 -0
- data/shibkit-meta_meta.gemspec +154 -0
- data/spec/meta_meta/attribute/token +0 -0
- data/spec/meta_meta/config/autoloading_and_refreshing_spec.rb +72 -0
- data/spec/meta_meta/config/code_nspec.rb +13 -0
- data/spec/meta_meta/config/configuration_spec.rb +30 -0
- data/spec/meta_meta/config/creation_spec.rb +43 -0
- data/spec/meta_meta/config/downloading_and_caching_settings_spec.rb +216 -0
- data/spec/meta_meta/config/env_platform_settings.rb +129 -0
- data/spec/meta_meta/config/filtering_settings_spec.rb +123 -0
- data/spec/meta_meta/config/init.rb +8 -0
- data/spec/meta_meta/config/logger_settings_spec.rb +91 -0
- data/spec/meta_meta/config/smartcache_settings_spec.rb +110 -0
- data/spec/meta_meta/config/source_file_settings_spec.rb +99 -0
- data/spec/meta_meta/config/tagging_settings_spec.rb +81 -0
- data/spec/meta_meta/config/working_directory_settings_spec.rb +106 -0
- data/spec/meta_meta/config/xml_processing_settings_spec.rb +75 -0
- data/spec/meta_meta/contact/contact_oldspec.rb +0 -0
- data/spec/meta_meta/entity/entity_oldspec.rb +53 -0
- data/spec/meta_meta/federation/federation_oldspec.rb +0 -0
- data/spec/meta_meta/idp/token +0 -0
- data/spec/meta_meta/logo/token +0 -0
- data/spec/meta_meta/meta_meta/cache_example.yaml +141284 -0
- data/spec/meta_meta/meta_meta/meta_meta_spec.rb +269 -0
- data/spec/meta_meta/meta_meta/saved_sources.yaml +46 -0
- data/spec/meta_meta/metadata_item/token +0 -0
- data/spec/meta_meta/organisation/organisation_oldspec.rb +0 -0
- data/spec/meta_meta/provider/token +0 -0
- data/spec/meta_meta/requested_attribute/token +0 -0
- data/spec/meta_meta/service/token +0 -0
- data/spec/meta_meta/source/application_extras_spec.rb +234 -0
- data/spec/meta_meta/source/conversion_spec.rb +75 -0
- data/spec/meta_meta/source/creation_spec.rb +0 -0
- data/spec/meta_meta/source/downloads_and_caching_spec.rb +0 -0
- data/spec/meta_meta/source/federation_information_spec.rb +11 -0
- data/spec/meta_meta/source/fixtures.rb +24 -0
- data/spec/meta_meta/source/init.rb +1 -0
- data/spec/meta_meta/source/loading_and_saving_spec.rb +0 -0
- data/spec/meta_meta/source/metadata_details_spec.rb +0 -0
- data/spec/meta_meta/source/metadata_integrity_spec.rb +0 -0
- data/spec/meta_meta/source/selection_spec.rb +0 -0
- data/spec/meta_meta/source/source_oldspec.rb +353 -0
- data/spec/meta_meta/source/xml_parsing_spec.rb +0 -0
- data/spec/meta_meta/sp/token +0 -0
- data/spec/meta_meta/template +2 -0
- data/spec/moi/config_spec.rb +0 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +25 -0
- data/spec/support/supply_xml.rb +0 -0
- metadata +320 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
## @author Pete Birkinshaw (<pete@digitalidentitylabs.com>)
|
|
2
|
+
## Copyright: Copyright (c) 2011 Digital Identity Ltd.
|
|
3
|
+
## License: Apache License, Version 2.0
|
|
4
|
+
|
|
5
|
+
## Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
## you may not use this file except in compliance with the License.
|
|
7
|
+
## You may obtain a copy of the License at
|
|
8
|
+
##
|
|
9
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
##
|
|
11
|
+
## Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
## distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
## See the License for the specific language governing permissions and
|
|
15
|
+
## limitations under the License.
|
|
16
|
+
##
|
|
17
|
+
|
|
18
|
+
module Shibkit
|
|
19
|
+
class MetaMeta
|
|
20
|
+
|
|
21
|
+
## Base class for all MetaMeta metadata classes
|
|
22
|
+
class MetadataItem
|
|
23
|
+
|
|
24
|
+
require 'nokogiri'
|
|
25
|
+
require 'digest/sha1'
|
|
26
|
+
|
|
27
|
+
## A few simple utility functions for slurping data from XML
|
|
28
|
+
require 'shibkit/meta_meta/mixin/xpath_chores'
|
|
29
|
+
include Shibkit::MetaMeta::Mixin::XPathChores
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
## Element and attribute used to select XML for new objects
|
|
33
|
+
ROOT_ELEMENT = 'SomeThingThatIsntThere'
|
|
34
|
+
TARGET_ATTR = 'ID'
|
|
35
|
+
REQUIRED_QUACKS = [:bananas]
|
|
36
|
+
|
|
37
|
+
## Additional namespaces that Nokogiri needs to know about
|
|
38
|
+
NAMESPACES = {
|
|
39
|
+
'ukfedlabel' => 'http://ukfederation.org.uk/2006/11/label',
|
|
40
|
+
'elab' => 'http://eduserv.org.uk/labels',
|
|
41
|
+
'wayf' => 'http://sdss.ac.uk/2006/06/WAYF',
|
|
42
|
+
'mdui' => 'urn:oasis:names:tc:SAML:metadata:ui',
|
|
43
|
+
'saml' => 'urn:oasis:names:tc:SAML:2.0:assertion',
|
|
44
|
+
'shibmd' => 'urn:mace:shibboleth:metadata:1.0'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
attr_reader :read_at
|
|
48
|
+
|
|
49
|
+
## New object takes XML (as libXML object or text)
|
|
50
|
+
def initialize(xml=nil, target=nil, options={}, &block)
|
|
51
|
+
|
|
52
|
+
@read_at = Time.new
|
|
53
|
+
@noko = nil
|
|
54
|
+
@source_xml = nil
|
|
55
|
+
|
|
56
|
+
## Use XML to build object
|
|
57
|
+
from_xml(xml) if xml
|
|
58
|
+
|
|
59
|
+
## Use block for further configuration or manual creation
|
|
60
|
+
self.instance_eval(&block) if block
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
## Make sure the object is suitable. Return nil if bad, object if good
|
|
65
|
+
def filter
|
|
66
|
+
|
|
67
|
+
## Make sure this object quacks like the suitable variety of duck
|
|
68
|
+
self.class::REQUIRED_QUACKS.each do |method|
|
|
69
|
+
|
|
70
|
+
return nil unless self.respond_to? method
|
|
71
|
+
return nil unless self.send(method)
|
|
72
|
+
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
return self
|
|
76
|
+
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def hashed_id
|
|
80
|
+
|
|
81
|
+
return Digest::SHA1.hexdigest uri || url || to_s
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def to_hash
|
|
86
|
+
|
|
87
|
+
raise "Not Implemented!"
|
|
88
|
+
|
|
89
|
+
return {}
|
|
90
|
+
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def to_rdf
|
|
94
|
+
|
|
95
|
+
raise "Not Implemented!"
|
|
96
|
+
|
|
97
|
+
return
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def to_xml
|
|
102
|
+
|
|
103
|
+
raise "Not Implemented!"
|
|
104
|
+
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def source_xml
|
|
110
|
+
|
|
111
|
+
return @source_xml
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def parsed_xml
|
|
116
|
+
|
|
117
|
+
prepare_xml(@noko) if @noko.kind_of? String
|
|
118
|
+
|
|
119
|
+
return @noko
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def purge_xml(cascade=true)
|
|
124
|
+
|
|
125
|
+
@noko = nil
|
|
126
|
+
@source_xml = nil
|
|
127
|
+
|
|
128
|
+
cascade_method(:purge_xml, true) if cascade
|
|
129
|
+
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def textify_xml(cascade=true)
|
|
133
|
+
|
|
134
|
+
@noko = @noko.to_s
|
|
135
|
+
|
|
136
|
+
cascade_method(:textify_xml, true) if cascade
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def from_xml(xml, target=nil, options={})
|
|
141
|
+
|
|
142
|
+
prepare_xml(xml)
|
|
143
|
+
select_xml(target, options)
|
|
144
|
+
parse_xml
|
|
145
|
+
purge_xml if ::Shibkit::MetaMeta.config.purge_xml?
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
private
|
|
150
|
+
|
|
151
|
+
def cascade_method(method_name, *params)
|
|
152
|
+
|
|
153
|
+
method_name = method_name.to_sym
|
|
154
|
+
|
|
155
|
+
self.instance_variables.each do |attr_name|
|
|
156
|
+
|
|
157
|
+
obj = instance_variable_get attr_name.to_sym
|
|
158
|
+
|
|
159
|
+
values = obj.values if obj.respond_to? :values
|
|
160
|
+
values ||= [obj].flatten
|
|
161
|
+
|
|
162
|
+
values.each do |value|
|
|
163
|
+
|
|
164
|
+
if value.respond_to? method_name
|
|
165
|
+
|
|
166
|
+
value.send method_name, *params
|
|
167
|
+
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
## Logging
|
|
177
|
+
def log
|
|
178
|
+
|
|
179
|
+
return ::Shibkit::MetaMeta.config.logger
|
|
180
|
+
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
## Make sure we have consistent Nokogiri document whether string or Nokogiri passed
|
|
184
|
+
def prepare_xml(xml)
|
|
185
|
+
|
|
186
|
+
if xml.kind_of? String
|
|
187
|
+
|
|
188
|
+
## Parse the entire file as an XML document
|
|
189
|
+
doc = Nokogiri::XML.parse(xml) do |config|
|
|
190
|
+
#config.strict.noent.dtdvalid
|
|
191
|
+
config.default_xml.nonet
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
@noko = doc.root
|
|
195
|
+
|
|
196
|
+
## Add exotic namespaces to make sure we can deal with all metadata
|
|
197
|
+
NAMESPACES.each_pair { |label, uri| @noko.add_namespace_definition(label,uri) }
|
|
198
|
+
|
|
199
|
+
@source_xml = xml if ::Shibkit::MetaMeta.config.remember_source_xml?
|
|
200
|
+
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
@noko ||= xml
|
|
204
|
+
|
|
205
|
+
## Make sure we get an element object...
|
|
206
|
+
@noko = @noko.at('/') if @noko.kind_of? Nokogiri::XML::NodeSet
|
|
207
|
+
@noko = @noko.root if @noko.kind_of? Nokogiri::XML::Document
|
|
208
|
+
|
|
209
|
+
raise "Unsuitable data!" unless @noko and @noko.respond_to? 'name'
|
|
210
|
+
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
## If a target is specified select first matching node, otherwise just grab first node of type
|
|
214
|
+
def select_xml(target=nil, options={})
|
|
215
|
+
|
|
216
|
+
unless @noko.name == self.class::ROOT_ELEMENT ## and check for target too
|
|
217
|
+
|
|
218
|
+
if target and TARGET_ATTR
|
|
219
|
+
selector = "xmlns:#{self.class::ROOT_ELEMENT}[@#{self.class::TARGET_ATTR}='#{target}'][1]"
|
|
220
|
+
@noko = @noko.xpath(selector)[0]
|
|
221
|
+
else
|
|
222
|
+
selector = "xmlns:#{self.class::ROOT_ELEMENT}[1]"
|
|
223
|
+
@noko = @noko.xpath(selector)[0]
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
raise "No suitable XML was selected: using #{selector}" unless @noko and
|
|
227
|
+
@noko.kind_of?(Nokogiri::XML::Element) and @noko.name
|
|
228
|
+
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
## Process XML to define object attributes
|
|
234
|
+
def parse_xml
|
|
235
|
+
|
|
236
|
+
raise "parse_xml method has not been implemented in this class"
|
|
237
|
+
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
## @author Pete Birkinshaw (<pete@digitalidentitylabs.com>)
|
|
2
|
+
## Copyright: Copyright (c) 2011 Digital Identity Ltd.
|
|
3
|
+
## License: Apache License, Version 2.0
|
|
4
|
+
|
|
5
|
+
## Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
## you may not use this file except in compliance with the License.
|
|
7
|
+
## You may obtain a copy of the License at
|
|
8
|
+
##
|
|
9
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
##
|
|
11
|
+
## Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
## distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
## See the License for the specific language governing permissions and
|
|
15
|
+
## limitations under the License.
|
|
16
|
+
##
|
|
17
|
+
|
|
18
|
+
module Shibkit
|
|
19
|
+
class MetaMeta
|
|
20
|
+
|
|
21
|
+
module Mixin
|
|
22
|
+
|
|
23
|
+
## A few simple utility functions for slurping data from XML
|
|
24
|
+
##
|
|
25
|
+
module CachedDownloads
|
|
26
|
+
|
|
27
|
+
require 'rest_client'
|
|
28
|
+
require 'restclient/components'
|
|
29
|
+
require 'rack/cache'
|
|
30
|
+
require 'rack/commonlogger'
|
|
31
|
+
require 'rbconfig'
|
|
32
|
+
require 'tempfile'
|
|
33
|
+
require 'addressable/uri'
|
|
34
|
+
require 'fileutils'
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Automatically add class methods to the including class
|
|
38
|
+
def self.included(receiver)
|
|
39
|
+
|
|
40
|
+
receiver.extend(CDClassMethods)
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
## Copy a filesystem file into the working directory (slower but safer)
|
|
45
|
+
def fetch_local(filename)
|
|
46
|
+
|
|
47
|
+
return unless filename
|
|
48
|
+
|
|
49
|
+
file_path = ::File.expand_path(filename)
|
|
50
|
+
raise "Can't access file #{file_path}!" unless ::File.exists?(file_path) and
|
|
51
|
+
::File.readable?(file_path)
|
|
52
|
+
|
|
53
|
+
file = Tempfile.new(Time.new.to_i.to_s)
|
|
54
|
+
open(file_path, 'w') { |f| f << http_response.to_s }
|
|
55
|
+
|
|
56
|
+
return file
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
## Copy a remote file into the working directory, also caching it for next update
|
|
61
|
+
def fetch_remote(url)
|
|
62
|
+
|
|
63
|
+
self.class.init_caches
|
|
64
|
+
|
|
65
|
+
http_response = RestClient.get(url)
|
|
66
|
+
|
|
67
|
+
file = Tempfile.new(Time.new.to_i.to_s)
|
|
68
|
+
open(file.path, 'w') { |f| f << http_response.to_s }
|
|
69
|
+
|
|
70
|
+
return file
|
|
71
|
+
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
## Class methods to mixin to including class
|
|
75
|
+
module CDClassMethods
|
|
76
|
+
|
|
77
|
+
##
|
|
78
|
+
## Class Methods
|
|
79
|
+
##
|
|
80
|
+
|
|
81
|
+
public
|
|
82
|
+
|
|
83
|
+
## Create the web cache
|
|
84
|
+
def init_caches
|
|
85
|
+
|
|
86
|
+
@initialised_caches ||= false
|
|
87
|
+
|
|
88
|
+
## Because these long class names are pain to keep typing
|
|
89
|
+
config = ::Shibkit::MetaMeta.config
|
|
90
|
+
|
|
91
|
+
unless @initialised_caches
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
## JIT loading of the Cache module so we can set options first
|
|
95
|
+
RestClient.enable Rack::Cache, config.download_cache_options
|
|
96
|
+
|
|
97
|
+
## Allow user to write log of all downloads in a standard format
|
|
98
|
+
if config.downloads_logger
|
|
99
|
+
|
|
100
|
+
RestClient.enable Rack::CommonLogger, config.downloads_logger
|
|
101
|
+
|
|
102
|
+
else
|
|
103
|
+
|
|
104
|
+
RestClient.disable Rack::CommonLogger
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@initialised_caches = true
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
## Helps if the locations actually exist, of course.
|
|
114
|
+
FileUtils.mkdir_p File.join(config.cache_root, 'meta')
|
|
115
|
+
FileUtils.mkdir_p File.join(config.cache_root, 'body')
|
|
116
|
+
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
## @author Pete Birkinshaw (<pete@digitalidentitylabs.com>)
|
|
2
|
+
## Copyright: Copyright (c) 2011 Digital Identity Ltd.
|
|
3
|
+
## License: Apache License, Version 2.0
|
|
4
|
+
|
|
5
|
+
## Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
## you may not use this file except in compliance with the License.
|
|
7
|
+
## You may obtain a copy of the License at
|
|
8
|
+
##
|
|
9
|
+
## http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
##
|
|
11
|
+
## Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
## distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
## See the License for the specific language governing permissions and
|
|
15
|
+
## limitations under the License.
|
|
16
|
+
##
|
|
17
|
+
|
|
18
|
+
module Shibkit
|
|
19
|
+
class MetaMeta
|
|
20
|
+
|
|
21
|
+
module Mixin
|
|
22
|
+
|
|
23
|
+
## A few simple utility functions for slurping data from XML
|
|
24
|
+
##
|
|
25
|
+
module XPathChores
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
## Return array of element contents when given xpath
|
|
30
|
+
def extract_simple_list(xpath)
|
|
31
|
+
|
|
32
|
+
results = Array.new
|
|
33
|
+
|
|
34
|
+
@noko.xpath(xpath).each do |ix|
|
|
35
|
+
|
|
36
|
+
results << ix.content.to_s.strip
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
return results
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
## Language-mapped Hash
|
|
45
|
+
def extract_lang_map_of_strings(xpath)
|
|
46
|
+
|
|
47
|
+
results = Hash.new
|
|
48
|
+
results[:en] = Array.new
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@noko.xpath(xpath).each do |ix|
|
|
52
|
+
|
|
53
|
+
lang = ix['lang'] || :en
|
|
54
|
+
results[lang.to_sym] = ix.content.strip.squeeze('')
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
return results
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
## Language-mapped Hash of string lists
|
|
63
|
+
def extract_lang_map_of_string_lists(xpath)
|
|
64
|
+
|
|
65
|
+
results = Hash.new
|
|
66
|
+
results[:en] = Array.new
|
|
67
|
+
|
|
68
|
+
@noko.xpath(xpath).each do |ix|
|
|
69
|
+
|
|
70
|
+
items = ix.content.split(' ')
|
|
71
|
+
items.each { |item| item.gsub!('+',' ') }
|
|
72
|
+
|
|
73
|
+
lang = ix['lang'] || :en
|
|
74
|
+
results[lang.to_sym] = items
|
|
75
|
+
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
return results
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
## Language-mapped Hash
|
|
83
|
+
def extract_lang_map_of_objects(xpath, req_class)
|
|
84
|
+
|
|
85
|
+
results = Hash.new
|
|
86
|
+
results[:en] = Array.new
|
|
87
|
+
|
|
88
|
+
@noko.xpath(xpath).each do |ix|
|
|
89
|
+
|
|
90
|
+
case req_class.respond_to?(:filter)
|
|
91
|
+
when true
|
|
92
|
+
obj = req_class.new(ix).filter
|
|
93
|
+
when false
|
|
94
|
+
obj = req_class.new(ix)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if obj
|
|
98
|
+
lang = ix['lang'] || :en
|
|
99
|
+
results[lang] ||= Array.new
|
|
100
|
+
results[lang] << obj
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
return results
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|