hdo-storting-importer 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +16 -0
- data/.gitmodules +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +8 -0
- data/LICENSE +20 -0
- data/README.md +14 -0
- data/Rakefile +11 -0
- data/bin/hdo-converter +7 -0
- data/features/import.feature +85 -0
- data/features/step_definitions/import_steps.rb +0 -0
- data/features/support/env.rb +7 -0
- data/hdo-storting-importer.gemspec +17 -0
- data/lib/hdo/storting_importer/api_data_source.rb +62 -0
- data/lib/hdo/storting_importer/category.rb +55 -0
- data/lib/hdo/storting_importer/cli.rb +141 -0
- data/lib/hdo/storting_importer/committee.rb +35 -0
- data/lib/hdo/storting_importer/converter.rb +45 -0
- data/lib/hdo/storting_importer/core_ext/enumerable.rb +12 -0
- data/lib/hdo/storting_importer/data_source.rb +22 -0
- data/lib/hdo/storting_importer/disk_data_source.rb +61 -0
- data/lib/hdo/storting_importer/district.rb +36 -0
- data/lib/hdo/storting_importer/issue.rb +90 -0
- data/lib/hdo/storting_importer/ivar_equality.rb +22 -0
- data/lib/hdo/storting_importer/parsing_data_source.rb +59 -0
- data/lib/hdo/storting_importer/party.rb +31 -0
- data/lib/hdo/storting_importer/promise.rb +49 -0
- data/lib/hdo/storting_importer/promise_converter.rb +48 -0
- data/lib/hdo/storting_importer/representative.rb +106 -0
- data/lib/hdo/storting_importer/script_importer.rb +20 -0
- data/lib/hdo/storting_importer/util.rb +26 -0
- data/lib/hdo/storting_importer/version.rb +5 -0
- data/lib/hdo/storting_importer/vote.rb +171 -0
- data/lib/hdo/storting_importer.rb +41 -0
- data/spec/fixtures/input/categories.xml +1351 -0
- data/spec/fixtures/input/committees.xml +92 -0
- data/spec/fixtures/input/districts.xml +101 -0
- data/spec/fixtures/input/issues.xml +2852 -0
- data/spec/fixtures/input/parties.xml +42 -0
- data/spec/fixtures/input/promises-a.csv +341 -0
- data/spec/fixtures/input/propositions_2175.xml +64 -0
- data/spec/fixtures/input/propositions_2176.xml +64 -0
- data/spec/fixtures/input/representatives.xml +3218 -0
- data/spec/fixtures/input/representatives_today.xml +4872 -0
- data/spec/fixtures/input/vote_results_2175.xml +4400 -0
- data/spec/fixtures/input/vote_results_2176.xml +4400 -0
- data/spec/fixtures/input/votes.xml +85 -0
- data/spec/fixtures/output/categories.xml +803 -0
- data/spec/fixtures/output/committees.xml +71 -0
- data/spec/fixtures/output/districts.xml +79 -0
- data/spec/fixtures/output/issues.xml +836 -0
- data/spec/fixtures/output/parties.xml +31 -0
- data/spec/fixtures/output/promises-a.xml +3224 -0
- data/spec/fixtures/output/representatives.xml +2567 -0
- data/spec/fixtures/output/votes.xml +4899 -0
- data/spec/hdo/storting_importer/category_spec.rb +76 -0
- data/spec/hdo/storting_importer/committee_spec.rb +46 -0
- data/spec/hdo/storting_importer/converter_spec.rb +72 -0
- data/spec/hdo/storting_importer/district_spec.rb +54 -0
- data/spec/hdo/storting_importer/issue_spec.rb +115 -0
- data/spec/hdo/storting_importer/party_spec.rb +52 -0
- data/spec/hdo/storting_importer/promise_spec.rb +38 -0
- data/spec/hdo/storting_importer/representative_spec.rb +81 -0
- data/spec/hdo/storting_importer/vote_spec.rb +155 -0
- data/spec/spec_helper.rb +39 -0
- metadata +145 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class Issue
|
4
|
+
include IvarEquality
|
5
|
+
|
6
|
+
attr_reader :external_id, :summary, :description, :type, :status, :last_update,
|
7
|
+
:reference, :document_group, :committee, :categories
|
8
|
+
|
9
|
+
def self.from_storting_doc(doc)
|
10
|
+
doc.css("saker_liste sak").map do |node|
|
11
|
+
from_storting_node(node)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.from_storting_node(node)
|
16
|
+
external_id = node.xpath("./id").first.text
|
17
|
+
summary = node.css("korttittel").first.text
|
18
|
+
description = Util.remove_newlines(node.css("tittel").first.text)
|
19
|
+
type = node.css("type").first.text
|
20
|
+
status = node.css("status").first.text
|
21
|
+
last_update = node.css("sist_oppdatert_dato").first.text
|
22
|
+
reference = node.css("henvisning").first.text
|
23
|
+
document_group = node.css("dokumentgruppe").first.text
|
24
|
+
|
25
|
+
committee_node = node.css("komite").first
|
26
|
+
if committee_node && committee_node['nil'] != "true"
|
27
|
+
committee = committee_node.css("navn").first.text
|
28
|
+
end
|
29
|
+
|
30
|
+
xcategories = node.css("emne")
|
31
|
+
if xcategories.any?
|
32
|
+
categories = xcategories.map { |xt| xt.css("navn").first.text }
|
33
|
+
end
|
34
|
+
|
35
|
+
new(external_id, summary, description, type, status, last_update, reference, document_group, committee, categories)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.from_hdo_node(node)
|
39
|
+
external_id = node.css("externalId").first.text
|
40
|
+
summary = node.css("summary").first.text
|
41
|
+
description = node.css("description").first.text
|
42
|
+
type = node.css("type").first.text
|
43
|
+
status = node.css("status").first.text
|
44
|
+
last_update = node.css("lastUpdate").first.text
|
45
|
+
reference = node.css("reference").first.text
|
46
|
+
document_group = node.css("documentGroup").first.text
|
47
|
+
committee = node.css("committee").first.text
|
48
|
+
categories = node.css("categories category").map { |e| e.text }
|
49
|
+
|
50
|
+
new external_id, summary, description, type, status, last_update, reference, document_group, committee, categories
|
51
|
+
end
|
52
|
+
|
53
|
+
def initialize(external_id, summary, description, type, status, last_update,
|
54
|
+
reference, document_group, committee, categories)
|
55
|
+
@external_id = external_id
|
56
|
+
@summary = summary
|
57
|
+
@description = description
|
58
|
+
@type = type
|
59
|
+
@status = status
|
60
|
+
@last_update = last_update
|
61
|
+
@reference = reference
|
62
|
+
@document_group = document_group
|
63
|
+
@committee = committee
|
64
|
+
@categories = categories || []
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_hdo_xml(builder = Util.builder)
|
68
|
+
builder.issue do |i|
|
69
|
+
i.externalId external_id
|
70
|
+
i.summary summary
|
71
|
+
i.description description
|
72
|
+
i.type type
|
73
|
+
i.status status
|
74
|
+
i.lastUpdate last_update
|
75
|
+
i.reference reference
|
76
|
+
i.documentGroup document_group
|
77
|
+
i.committee(committee) if committee
|
78
|
+
|
79
|
+
if categories.any?
|
80
|
+
i.categories do |cats|
|
81
|
+
categories.each { |e| cats.category e }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
module IvarEquality
|
4
|
+
|
5
|
+
def ==(other)
|
6
|
+
other.kind_of?(self.class) && __ivars__ == other.__ivars__
|
7
|
+
end
|
8
|
+
alias_method :eql?, :==
|
9
|
+
|
10
|
+
def hash
|
11
|
+
__ivars__.hash ^ self.class.hash
|
12
|
+
end
|
13
|
+
|
14
|
+
def __ivars__
|
15
|
+
res = {}
|
16
|
+
instance_variables.each { |e| res[e] = instance_variable_get(e) }
|
17
|
+
|
18
|
+
res
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class ParsingDataSource < DataSource
|
4
|
+
def initialize(delegate_data_source)
|
5
|
+
@data_source = delegate_data_source
|
6
|
+
end
|
7
|
+
|
8
|
+
def representatives(period = DEFAULT_PERIOD)
|
9
|
+
Representative.from_storting_doc @data_source.representatives(period)
|
10
|
+
end
|
11
|
+
|
12
|
+
def representatives_today
|
13
|
+
Representative.from_storting_doc @data_source.representatives_today
|
14
|
+
end
|
15
|
+
|
16
|
+
def parties(session_id = DEFAULT_SESSION)
|
17
|
+
Party.from_storting_doc @data_source.parties(session_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
def committees(session_id = DEFAULT_SESSION)
|
21
|
+
Committee.from_storting_doc @data_source.committees(session_id)
|
22
|
+
end
|
23
|
+
|
24
|
+
def districts
|
25
|
+
District.from_storting_doc @data_source.districts
|
26
|
+
end
|
27
|
+
|
28
|
+
def categories
|
29
|
+
Category.from_storting_doc @data_source.categories
|
30
|
+
end
|
31
|
+
|
32
|
+
def issues(session_id = DEFAULT_SESSION)
|
33
|
+
Issue.from_storting_doc @data_source.issues(session_id)
|
34
|
+
end
|
35
|
+
|
36
|
+
def votes_for(issue_id)
|
37
|
+
votes = Vote.from_storting_doc @data_source.votes_for(issue_id)
|
38
|
+
|
39
|
+
votes.each do |vote|
|
40
|
+
vote.add_storting_propositions @data_source.propositions_for(vote.external_id)
|
41
|
+
if vote.personal?
|
42
|
+
vote.add_storting_results @data_source.vote_results_for(vote.external_id)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
votes
|
47
|
+
end
|
48
|
+
|
49
|
+
def propositions_for(vote_id)
|
50
|
+
raise NotImplementedError, 'result of #votes_for includes propositions'
|
51
|
+
end
|
52
|
+
|
53
|
+
def vote_results_for(vote_id)
|
54
|
+
raise NotImplementedError, 'result of #votes_for includes vote results'
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class Party
|
4
|
+
include IvarEquality
|
5
|
+
|
6
|
+
attr_reader :external_id, :name
|
7
|
+
|
8
|
+
def self.from_storting_doc(doc)
|
9
|
+
doc.css("partier_liste parti").map do |node|
|
10
|
+
new node.css("id").first.text, node.css("navn").first.text
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.from_hdo_node(node)
|
15
|
+
new node.css("externalId").first.text, node.css("name").first.text
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(external_id, name)
|
19
|
+
@external_id = external_id
|
20
|
+
@name = name
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_hdo_xml(builder = Util.builder)
|
24
|
+
builder.party do |party|
|
25
|
+
party.externalId external_id
|
26
|
+
party.name name
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module Hdo
|
4
|
+
module StortingImporter
|
5
|
+
class Promise
|
6
|
+
attr_reader :party, :body, :general, :categories, :source, :page
|
7
|
+
alias_method :general?, :general
|
8
|
+
|
9
|
+
def self.from_csv(str)
|
10
|
+
# cleanup
|
11
|
+
str.gsub!(/\bFrp\b/, "FrP")
|
12
|
+
str.gsub!(/\bKrf\b/, "KrF")
|
13
|
+
str.gsub!(/\bSP\b/, "Sp")
|
14
|
+
|
15
|
+
rows = CSV.parse(
|
16
|
+
str,
|
17
|
+
headers: [:party, :body, :general, :categories, :source, :page],
|
18
|
+
col_sep: ";",
|
19
|
+
skip_blanks: true,
|
20
|
+
return_headers: false,
|
21
|
+
)
|
22
|
+
|
23
|
+
rows.map do |e|
|
24
|
+
pr = e.to_hash
|
25
|
+
next if pr[:party].to_s.strip == "Parti" # header row
|
26
|
+
|
27
|
+
new(
|
28
|
+
pr[:party].to_s.strip,
|
29
|
+
pr[:body].to_s.strip,
|
30
|
+
pr[:general].to_s.downcase == 'ja',
|
31
|
+
pr[:categories].split(",").map(&:upcase).map(&:strip),
|
32
|
+
pr[:source].to_s.strip,
|
33
|
+
pr[:page].to_s.strip
|
34
|
+
)
|
35
|
+
end.compact
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(party, body, general, categories, source, page)
|
39
|
+
@party = party
|
40
|
+
@body = body
|
41
|
+
@general = general
|
42
|
+
@categories = categories
|
43
|
+
@source = source
|
44
|
+
@page = page
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
require 'builder'
|
5
|
+
|
6
|
+
module Hdo
|
7
|
+
module StortingImporter
|
8
|
+
class PromiseConverter
|
9
|
+
def initialize(exported_spreadsheet)
|
10
|
+
content = File.read(File.expand_path(exported_spreadsheet), encoding: "ISO-8859-1").encode("UTF-8")
|
11
|
+
@promises = Promise.from_csv(content)
|
12
|
+
end
|
13
|
+
|
14
|
+
def xml
|
15
|
+
builder = Builder::XmlMarkup.new :indent => 2
|
16
|
+
builder.instruct!
|
17
|
+
|
18
|
+
builder.promises do |promises|
|
19
|
+
@promises.each do |data|
|
20
|
+
next if data.body == "Løftetekst" || data.body.nil? || data.body.empty?
|
21
|
+
add_promise(promises, data)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
builder.target!
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_promise(promises, data)
|
29
|
+
promises.promise do |promise|
|
30
|
+
promise.party data.party.strip
|
31
|
+
promise.general data.general
|
32
|
+
promise.categories do |categories|
|
33
|
+
data.categories.each do |name|
|
34
|
+
categories.category name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
promise.source [data.source, data.page].join(":")
|
39
|
+
promise.body data.body.strip
|
40
|
+
end
|
41
|
+
rescue
|
42
|
+
STDERR.puts data.inspect
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class Representative
|
4
|
+
include IvarEquality
|
5
|
+
|
6
|
+
attr_reader :external_id, :first_name, :last_name, :date_of_birth, :date_of_death,
|
7
|
+
:district, :party, :committees, :period, :gender
|
8
|
+
|
9
|
+
attr_accessor :vote_result
|
10
|
+
|
11
|
+
def self.from_storting_doc(doc)
|
12
|
+
nodes = doc.css("dagensrepresentant")
|
13
|
+
nodes += doc.css("representant")
|
14
|
+
|
15
|
+
nodes.map { |e| from_storting_node(e) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.from_storting_node(node)
|
19
|
+
district_node = node.css("fylke navn").first
|
20
|
+
district = district_node ? district_node.text : ''
|
21
|
+
|
22
|
+
party_node = node.css("parti navn").first
|
23
|
+
party = party_node ? party_node.text : ''
|
24
|
+
|
25
|
+
committees = node.css("komite").map { |c| c.css("navn").text.strip }
|
26
|
+
period = '2011-2012' # FIXME
|
27
|
+
|
28
|
+
new(
|
29
|
+
node.css("id").first.text,
|
30
|
+
node.css("fornavn").first.text,
|
31
|
+
node.css("etternavn").first.text,
|
32
|
+
node.css("kjoenn").first.text == "mann" ? 'M' : 'F',
|
33
|
+
node.css("foedselsdato").first.text,
|
34
|
+
node.css("doedsdato").first.text,
|
35
|
+
district,
|
36
|
+
party,
|
37
|
+
committees,
|
38
|
+
period
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.from_hdo_node(node)
|
43
|
+
district_node = node.css("district").first
|
44
|
+
district = district_node ? district_node.text : ''
|
45
|
+
|
46
|
+
party_node = node.css("party").first
|
47
|
+
party = party_node ? party_node.text : ''
|
48
|
+
|
49
|
+
rep = new node.css("externalId").first.text,
|
50
|
+
node.css("firstName").first.text,
|
51
|
+
node.css("lastName").first.text,
|
52
|
+
node.css("gender").first.text,
|
53
|
+
node.css("dateOfBirth").first.text,
|
54
|
+
node.css("dateOfDeath").first.text,
|
55
|
+
district,
|
56
|
+
party,
|
57
|
+
node.css("committees committee").map { |e| e.text.strip },
|
58
|
+
node.css("period").first.text
|
59
|
+
|
60
|
+
result_node = node.css("voteResult").first
|
61
|
+
rep.vote_result = result_node.text if result_node
|
62
|
+
|
63
|
+
rep
|
64
|
+
end
|
65
|
+
|
66
|
+
def initialize(external_id, first_name, last_name, gender, date_of_birth, date_of_death, district, party, committees, period)
|
67
|
+
@external_id = external_id
|
68
|
+
@first_name = first_name
|
69
|
+
@last_name = last_name
|
70
|
+
@gender = gender
|
71
|
+
@date_of_birth = date_of_birth
|
72
|
+
@date_of_death = date_of_death
|
73
|
+
@district = district
|
74
|
+
@party = party
|
75
|
+
@committees = committees
|
76
|
+
@period = period
|
77
|
+
|
78
|
+
@vote_result = nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_hdo_xml(builder = Util.builder)
|
82
|
+
builder.representative do |rep|
|
83
|
+
rep.externalId external_id
|
84
|
+
rep.firstName first_name
|
85
|
+
rep.lastName last_name
|
86
|
+
rep.gender gender
|
87
|
+
rep.dateOfBirth date_of_birth
|
88
|
+
rep.dateOfDeath date_of_death
|
89
|
+
rep.district district
|
90
|
+
rep.party party
|
91
|
+
|
92
|
+
rep.committees do |coms|
|
93
|
+
committees.each { |e| coms.committee e }
|
94
|
+
end
|
95
|
+
|
96
|
+
rep.period period
|
97
|
+
|
98
|
+
if vote_result
|
99
|
+
rep.voteResult vote_result
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class ScriptImporter
|
4
|
+
|
5
|
+
def initialize(app_root)
|
6
|
+
@app_root = app_root
|
7
|
+
end
|
8
|
+
|
9
|
+
def import(xml)
|
10
|
+
Tempfile.open("storting2hdo") do |f|
|
11
|
+
f << xml
|
12
|
+
f.close
|
13
|
+
|
14
|
+
Dir.chdir(@app_root) { system "script/import", f.path }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
module Util
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def builder
|
7
|
+
xml = Builder::XmlMarkup.new :indent => 2
|
8
|
+
|
9
|
+
if block_given?
|
10
|
+
yield xml
|
11
|
+
return xml.target!
|
12
|
+
end
|
13
|
+
|
14
|
+
xml
|
15
|
+
end
|
16
|
+
|
17
|
+
def remove_newlines(str)
|
18
|
+
str.gsub(/\r?\n/, '')
|
19
|
+
end
|
20
|
+
|
21
|
+
def remove_invalid_html(str)
|
22
|
+
str.gsub("<\\p>", "")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
class Vote
|
4
|
+
include IvarEquality
|
5
|
+
|
6
|
+
attr_reader :external_id, :external_issue_id, :personal, :enacted, :subject,
|
7
|
+
:method, :result_type, :time, :counts
|
8
|
+
attr_accessor :propositions, :representatives
|
9
|
+
|
10
|
+
alias_method :personal?, :personal
|
11
|
+
alias_method :enacted?, :enacted
|
12
|
+
|
13
|
+
def self.from_storting_doc(doc)
|
14
|
+
issue_id = doc.css("sak_id").first.text
|
15
|
+
|
16
|
+
doc.css("sak_votering").map do |vote_node|
|
17
|
+
vote_id = vote_node.css("votering_id").text
|
18
|
+
personal = vote_node.css("personlig_votering").text == "true"
|
19
|
+
enacted = vote_node.css("vedtatt").text == "true"
|
20
|
+
subject = vote_node.css("votering_tema").text
|
21
|
+
method = vote_node.css("votering_metode").text
|
22
|
+
result_type = vote_node.css("votering_resultat_type").text
|
23
|
+
time = vote_node.css("votering_tid").text
|
24
|
+
|
25
|
+
forc = Integer(vote_node.css("antall_for").text)
|
26
|
+
againstc = Integer(vote_node.css("antall_mot").text)
|
27
|
+
absentc = Integer(vote_node.css("antall_ikke_tilstede").text)
|
28
|
+
|
29
|
+
# settes til -1 ved personlig_votering=false
|
30
|
+
forc = 0 if forc < 0
|
31
|
+
againstc = 0 if againstc < 0
|
32
|
+
absentc = 0 if absentc < 0
|
33
|
+
|
34
|
+
new vote_id, issue_id, personal, enacted, subject, method, result_type, time, forc, againstc, absentc
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.from_hdo_node(node)
|
39
|
+
external_id = node.css("externalId").first.text
|
40
|
+
external_issue_id = node.css("externalIssueId").first.text
|
41
|
+
for_count = node.css("counts for").first.text
|
42
|
+
against_count = node.css("counts against").first.text
|
43
|
+
absent_count = node.css("counts absent").first.text
|
44
|
+
personal = node.css("personal").first.text == 'true'
|
45
|
+
enacted = node.css("enacted").first.text == 'true'
|
46
|
+
subject = node.css("subject").first.text
|
47
|
+
method = node.css("method").first.text
|
48
|
+
result_type = node.css("resultType").first.text
|
49
|
+
time = node.css("time").first.text
|
50
|
+
|
51
|
+
vote = new external_id, external_issue_id, personal, enacted, subject, method, result_type, time, for_count, against_count, absent_count
|
52
|
+
vote.propositions = node.css("propositions proposition").map { |e| Proposition.from_hdo_node(e) }
|
53
|
+
vote.representatives = node.css("representatives representative").map { |e| Representative.from_hdo_node(e) }
|
54
|
+
|
55
|
+
vote
|
56
|
+
end
|
57
|
+
|
58
|
+
def initialize(external_id, external_issue_id, personal, enacted, subject, method, result_type, time, for_count, against_count, absent_count)
|
59
|
+
@external_id = external_id
|
60
|
+
@external_issue_id = external_issue_id
|
61
|
+
@personal = personal
|
62
|
+
@enacted = enacted
|
63
|
+
@subject = subject
|
64
|
+
@method = method
|
65
|
+
@result_type = result_type
|
66
|
+
@time = time
|
67
|
+
@counts = Counts.new(Integer(for_count), Integer(against_count), Integer(absent_count))
|
68
|
+
|
69
|
+
@propositions = []
|
70
|
+
@representatives = []
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_storting_propositions(node)
|
74
|
+
@propositions += node.css("voteringsforslag").map do |n|
|
75
|
+
rep_node = n.css("forslag_levert_av_representant").first
|
76
|
+
if rep_node && rep_node['nil'] != 'true'
|
77
|
+
delivered_by = Representative.from_storting_node(rep_node)
|
78
|
+
else
|
79
|
+
delivered_by = nil
|
80
|
+
end
|
81
|
+
|
82
|
+
Proposition.new n.css("forslag_id").first.text,
|
83
|
+
n.css("forslag_betegnelse").first.text,
|
84
|
+
n.css("forslag_paa_vegne_av_tekst").first.text,
|
85
|
+
Util.remove_invalid_html(n.css("forslag_tekst").first.text),
|
86
|
+
delivered_by
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def add_storting_results(node)
|
92
|
+
@representatives += node.css("representant_voteringsresultat").map do |n|
|
93
|
+
rep = Representative.from_storting_node(n.css("representant").first)
|
94
|
+
rep.vote_result = case n.css("votering").text
|
95
|
+
when 'for'
|
96
|
+
'for'
|
97
|
+
when 'mot'
|
98
|
+
'against'
|
99
|
+
when 'ikke_tilstede'
|
100
|
+
'absent'
|
101
|
+
else
|
102
|
+
raise "unexpected vote: #{vote_result.inspect}"
|
103
|
+
end
|
104
|
+
|
105
|
+
rep
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def to_hdo_xml(builder = Util.builder)
|
110
|
+
builder.vote do |vote|
|
111
|
+
vote.externalId external_id
|
112
|
+
vote.externalIssueId external_issue_id
|
113
|
+
vote.counts do |c|
|
114
|
+
c.for counts.for
|
115
|
+
c.against counts.against
|
116
|
+
c.absent counts.absent
|
117
|
+
end
|
118
|
+
vote.personal personal?
|
119
|
+
vote.enacted enacted?
|
120
|
+
vote.subject subject
|
121
|
+
vote.method method
|
122
|
+
vote.resultType result_type
|
123
|
+
vote.time time
|
124
|
+
|
125
|
+
vote.representatives do |reps|
|
126
|
+
representatives.each do |rep|
|
127
|
+
rep.to_hdo_xml(reps)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
vote.propositions do |props|
|
132
|
+
propositions.each do |prop|
|
133
|
+
prop.to_hdo_xml(props)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class Counts < Struct.new(:for, :against, :absent)
|
140
|
+
end
|
141
|
+
|
142
|
+
class Proposition < Struct.new(:external_id, :description, :on_behalf_of, :body, :delivered_by)
|
143
|
+
def self.from_hdo_node(node)
|
144
|
+
external_id = node.css("externalId").first.text
|
145
|
+
description = node.css("description").first.text
|
146
|
+
on_behalf_of = node.css("onBehalfOf").first.text
|
147
|
+
body = node.css("body").first.text
|
148
|
+
|
149
|
+
delivered_by_node = node.css("deliveredBy representative").first
|
150
|
+
delivered_by = Representative.from_hdo_node(delivered_by_node) if delivered_by_node
|
151
|
+
|
152
|
+
new external_id, description, on_behalf_of, body, delivered_by
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_hdo_xml(builder)
|
156
|
+
builder.proposition do |pr|
|
157
|
+
pr.externalId external_id
|
158
|
+
pr.description description
|
159
|
+
pr.onBehalfOf on_behalf_of
|
160
|
+
pr.body body
|
161
|
+
|
162
|
+
pr.deliveredBy do |db|
|
163
|
+
delivered_by.to_hdo_xml(db) if delivered_by
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end # Proposition
|
168
|
+
|
169
|
+
end # Vote
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Hdo
|
2
|
+
module StortingImporter
|
3
|
+
def self.root
|
4
|
+
@root ||= File.expand_path("../../..", __FILE__)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'nokogiri'
|
10
|
+
require 'restclient'
|
11
|
+
require 'tempfile'
|
12
|
+
require 'pathname'
|
13
|
+
require 'open-uri'
|
14
|
+
require 'erb'
|
15
|
+
require 'logger'
|
16
|
+
|
17
|
+
require 'hdo/storting_importer/core_ext/enumerable'
|
18
|
+
require 'hdo/storting_importer/ivar_equality'
|
19
|
+
require 'hdo/storting_importer/util'
|
20
|
+
|
21
|
+
require 'hdo/storting_importer/data_source'
|
22
|
+
require 'hdo/storting_importer/disk_data_source'
|
23
|
+
require 'hdo/storting_importer/api_data_source'
|
24
|
+
require 'hdo/storting_importer/parsing_data_source'
|
25
|
+
require 'hdo/storting_importer/script_importer'
|
26
|
+
|
27
|
+
require 'hdo/storting_importer/category'
|
28
|
+
require 'hdo/storting_importer/committee'
|
29
|
+
require 'hdo/storting_importer/district'
|
30
|
+
require 'hdo/storting_importer/issue'
|
31
|
+
require 'hdo/storting_importer/party'
|
32
|
+
require 'hdo/storting_importer/promise'
|
33
|
+
require 'hdo/storting_importer/representative'
|
34
|
+
require 'hdo/storting_importer/vote'
|
35
|
+
|
36
|
+
require 'hdo/storting_importer/converter'
|
37
|
+
require 'hdo/storting_importer/promise_converter'
|
38
|
+
|
39
|
+
require 'hdo/storting_importer/cli'
|
40
|
+
|
41
|
+
|