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