slaw 9.2.0 → 10.0.0
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.
- checksums.yaml +4 -4
- data/README.md +10 -1
- data/bin/slaw +7 -1
- data/lib/slaw/grammars/counters.rb +22 -5
- data/lib/slaw/grammars/schedules_nodes.rb +11 -14
- data/lib/slaw/grammars/tables_nodes.rb +3 -1
- data/lib/slaw/grammars/za/act_nodes.rb +34 -32
- data/lib/slaw/grammars/za/act_text.xsl +6 -23
- data/lib/slaw/namespace.rb +9 -3
- data/lib/slaw/parse/blocklists.rb +10 -9
- data/lib/slaw/parse/builder.rb +1 -4
- data/lib/slaw/schemas/akomantoso30.xsd +6862 -0
- data/lib/slaw/version.rb +1 -1
- data/lib/slaw/xml_support.rb +1 -67
- data/spec/fixtures/community-fire-safety.xml +15 -15
- data/spec/generator_spec.rb +1 -1
- data/spec/parse/blocklists_spec.rb +169 -169
- data/spec/xml_helpers.rb +2 -2
- data/spec/za/act_block_spec.rb +266 -266
- data/spec/za/act_inline_spec.rb +67 -69
- data/spec/za/act_schedules_spec.rb +312 -348
- data/spec/za/act_table_spec.rb +45 -47
- data/spec/za/postprocess_spec.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ada9248a6af947faeae4212b3d1cffe7b912d90712baf8c7273cc0fbb107c926
|
4
|
+
data.tar.gz: 01ea2d767da2b46bdbaea17566998c46b09e293e334a454e5022d63104981021
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04a40af1f73282bdf912213451ca7e37e7538a77373c42ae294979bf91bf240b0a22e4b09e3816f303324f3e6e463cf2d16f81b240fd94d692e13c9fe0dc1d87
|
7
|
+
data.tar.gz: 49cb6f91a31977c3bc6808baee29da7e014a4743d677234b9da83d1ec9cfbdd539daee2b03d6b9878382d7b4bd0b63fe6227f8f083151d412bced1dbc40ef6a1
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Slaw [](http://travis-ci.org/longhotsummer/slaw) [](https://badge.fury.io/rb/slaw)
|
2
2
|
|
3
|
-
Slaw is a lightweight library for generating Akoma Ntoso
|
3
|
+
Slaw is a lightweight library for generating Akoma Ntoso 3.0 Act XML from plain text documents.
|
4
4
|
It is used to power [Indigo](https://github.com/laws-africa/indigo) and uses grammars developed for the legal
|
5
5
|
tradition in South Africa, although others traditions are supported.
|
6
6
|
|
@@ -86,6 +86,15 @@ You can create your own grammar by creating a gem that provides these files and
|
|
86
86
|
|
87
87
|
## Changelog
|
88
88
|
|
89
|
+
### 10.0.0 (12 June 2020)
|
90
|
+
|
91
|
+
* BREAKING: Create XML with AKN 3 namespace (http://docs.oasis-open.org/legaldocml/ns/akn/3.0), AKN2 is no longer supported
|
92
|
+
* BREAKING: replace id attributes with eId attributes
|
93
|
+
* BREAKING: serialize schedules as attachments to act, not as components as peers of the act
|
94
|
+
* BREAKING: anonymous blocks are serialized as hcontainers, not paragraphs
|
95
|
+
* BREAKING: crossheading hcontainer IDs correctly use hcontainer
|
96
|
+
* Remove unnecessary schemaLocation header in root element
|
97
|
+
|
89
98
|
### 9.2.0 (10 June 2020)
|
90
99
|
|
91
100
|
* Subpart numbers are optional
|
data/bin/slaw
CHANGED
@@ -19,6 +19,7 @@ class SlawCLI < Thor
|
|
19
19
|
option :section_number_position, enum: ['before-title', 'after-title', 'guess'], desc: "Where do section titles come in relation to the section number? Default: before-title"
|
20
20
|
option :grammar, type: :string, desc: "Grammar name (usually a two-letter country code). Default is za."
|
21
21
|
option :ascii, type: :boolean, default: false, desc: "Process text as ASCII using %-encoding. This can provide significant speed improvements if the grammar uses only ASCII literals. See https://github.com/cjheath/treetop/issues/31."
|
22
|
+
option :namespace, enum: ['akn3'], default: 'akn3', desc: 'AKN XML namespace to use.'
|
22
23
|
def parse(name)
|
23
24
|
logging
|
24
25
|
|
@@ -33,6 +34,11 @@ class SlawCLI < Thor
|
|
33
34
|
text = extractor.extract_from_file(name)
|
34
35
|
end
|
35
36
|
|
37
|
+
case options[:namespace]
|
38
|
+
when 'akn3'
|
39
|
+
Slaw.akn_namespace = Slaw::AKN3_NS
|
40
|
+
end
|
41
|
+
|
36
42
|
generator = Slaw::ActGenerator.new(options[:grammar] || 'za')
|
37
43
|
|
38
44
|
if options[:fragment]
|
@@ -49,7 +55,7 @@ class SlawCLI < Thor
|
|
49
55
|
|
50
56
|
if options[:id_prefix]
|
51
57
|
prefix = options[:id_prefix]
|
52
|
-
prefix += "
|
58
|
+
prefix += "__" unless prefix.end_with?('__')
|
53
59
|
generator.builder.fragment_id_prefix = prefix
|
54
60
|
end
|
55
61
|
end
|
@@ -4,16 +4,14 @@ module Slaw
|
|
4
4
|
# Counters for generating element IDs. This is a hash from the element ID
|
5
5
|
# prefix, to another hash that maps the element type name to a count.
|
6
6
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# This is NOT compatible with AKN 3.0 which requires that element numbers
|
10
|
-
# start at 1.
|
7
|
+
# Counters always start at 0, and must be incremented before being used.
|
8
|
+
# This ensures that element ids start at 1, as per AKN 3.0 spec.
|
11
9
|
#
|
12
10
|
# eg.
|
13
11
|
#
|
14
12
|
# section-1 => paragraph => 2
|
15
13
|
#
|
16
|
-
@@counters = Hash.new{ |h, k| h[k] = Hash.new(
|
14
|
+
@@counters = Hash.new{ |h, k| h[k] = Hash.new(0) }
|
17
15
|
|
18
16
|
def self.counters
|
19
17
|
@@counters
|
@@ -22,6 +20,25 @@ module Slaw
|
|
22
20
|
def self.reset!
|
23
21
|
@@counters.clear
|
24
22
|
end
|
23
|
+
|
24
|
+
# Clean a <num> value for use in an eId
|
25
|
+
# See https://docs.oasis-open.org/legaldocml/akn-nc/v1.0/os/akn-nc-v1.0-os.html#_Toc531692306
|
26
|
+
#
|
27
|
+
# The number part of the identifiers of such elements corresponds to the
|
28
|
+
# stripping of all final punctuation, meaningless separations as well as
|
29
|
+
# redundant characters in the content of the <num> element. The
|
30
|
+
# representation is case-sensitive
|
31
|
+
#
|
32
|
+
# (i) -> i
|
33
|
+
# 1.2. -> 1-2
|
34
|
+
# 3a bis -> 3abis
|
35
|
+
def self.clean(num)
|
36
|
+
num
|
37
|
+
.gsub(/[ ()\[\]]/, '')
|
38
|
+
.gsub(/\.+$/, '')
|
39
|
+
.gsub(/^\.+/, '')
|
40
|
+
.gsub(/\.+/, '-')
|
41
|
+
end
|
25
42
|
end
|
26
43
|
end
|
27
44
|
end
|
@@ -10,7 +10,7 @@ module Slaw
|
|
10
10
|
|
11
11
|
class ScheduleContainer < Treetop::Runtime::SyntaxNode
|
12
12
|
def to_xml(b, idprefix="")
|
13
|
-
b.
|
13
|
+
b.attachments { |b|
|
14
14
|
schedules.children.elements.each_with_index { |e, i|
|
15
15
|
e.to_xml(b, idprefix, i+1)
|
16
16
|
}
|
@@ -86,6 +86,9 @@ module Slaw
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def to_xml(b, idprefix=nil, i=1)
|
89
|
+
# reset counters for this new schedule document
|
90
|
+
Slaw::Grammars::Counters.reset!
|
91
|
+
|
89
92
|
heading_text = self.schedule_title.heading_text
|
90
93
|
if not heading_text
|
91
94
|
heading_text = "Schedule"
|
@@ -95,12 +98,13 @@ module Slaw
|
|
95
98
|
# the schedule id is derived from the heading
|
96
99
|
schedule_id = self.schedule_id(heading_text, i)
|
97
100
|
|
98
|
-
b.
|
99
|
-
|
101
|
+
b.attachment(eId: "att_#{i}") { |b|
|
102
|
+
schedule_title.to_xml(b, '', heading_text)
|
103
|
+
b.doc_(name: "schedule") { |b|
|
100
104
|
b.meta { |b|
|
101
105
|
b.identification(source: "#slaw") { |b|
|
102
106
|
b.FRBRWork { |b|
|
103
|
-
b.FRBRthis(value: "#{WORK_URI}
|
107
|
+
b.FRBRthis(value: "#{WORK_URI}/!#{schedule_id}")
|
104
108
|
b.FRBRuri(value: WORK_URI)
|
105
109
|
b.FRBRalias(value: heading_text)
|
106
110
|
b.FRBRdate(date: '1980-01-01', name: 'Generation')
|
@@ -108,14 +112,14 @@ module Slaw
|
|
108
112
|
b.FRBRcountry(value: 'za')
|
109
113
|
}
|
110
114
|
b.FRBRExpression { |b|
|
111
|
-
b.FRBRthis(value: "#{EXPRESSION_URI}
|
115
|
+
b.FRBRthis(value: "#{EXPRESSION_URI}/!#{schedule_id}")
|
112
116
|
b.FRBRuri(value: EXPRESSION_URI)
|
113
117
|
b.FRBRdate(date: '1980-01-01', name: 'Generation')
|
114
118
|
b.FRBRauthor(href: '#council')
|
115
119
|
b.FRBRlanguage(language: 'eng')
|
116
120
|
}
|
117
121
|
b.FRBRManifestation { |b|
|
118
|
-
b.FRBRthis(value: "#{MANIFESTATION_URI}
|
122
|
+
b.FRBRthis(value: "#{MANIFESTATION_URI}/!#{schedule_id}")
|
119
123
|
b.FRBRuri(value: MANIFESTATION_URI)
|
120
124
|
b.FRBRdate(date: Time.now.strftime('%Y-%m-%d'), name: 'Generation')
|
121
125
|
b.FRBRauthor(href: '#slaw')
|
@@ -124,14 +128,7 @@ module Slaw
|
|
124
128
|
}
|
125
129
|
|
126
130
|
b.mainBody { |b|
|
127
|
-
|
128
|
-
|
129
|
-
# there is no good AKN hierarchy container for schedules, so we
|
130
|
-
# use hcontainer instead
|
131
|
-
b.hcontainer(id: schedule_id, name: "schedule") { |b|
|
132
|
-
schedule_title.to_xml(b, idprefix, heading_text)
|
133
|
-
body.children.elements.each_with_index { |e| e.to_xml(b, idprefix, i) } if body.is_a? Body
|
134
|
-
}
|
131
|
+
body.children.elements.each_with_index { |e| e.to_xml(b, '', i) } if body.is_a? Body
|
135
132
|
}
|
136
133
|
}
|
137
134
|
}
|
@@ -3,7 +3,9 @@ module Slaw
|
|
3
3
|
module Tables
|
4
4
|
class Table < Treetop::Runtime::SyntaxNode
|
5
5
|
def to_xml(b, idprefix, i=0)
|
6
|
-
|
6
|
+
cnt = Slaw::Grammars::Counters.counters[idprefix]['table'] += 1
|
7
|
+
|
8
|
+
b.table(eId: "#{idprefix}table_#{cnt}") { |b|
|
7
9
|
# we'll gather cells into this row list
|
8
10
|
rows = []
|
9
11
|
cells = []
|
@@ -12,13 +12,13 @@ module Slaw
|
|
12
12
|
MANIFESTATION_URI = EXPRESSION_URI
|
13
13
|
|
14
14
|
def to_xml(b, idprefix=nil, i=0)
|
15
|
-
b.act(contains:
|
15
|
+
b.act(contains: 'originalVersion', name: 'act') { |b|
|
16
16
|
write_meta(b)
|
17
17
|
write_preface(b)
|
18
18
|
write_preamble(b)
|
19
19
|
write_body(b)
|
20
|
+
write_schedules(b)
|
20
21
|
}
|
21
|
-
write_schedules(b)
|
22
22
|
end
|
23
23
|
|
24
24
|
def write_meta(b)
|
@@ -26,8 +26,8 @@ module Slaw
|
|
26
26
|
write_identification(b)
|
27
27
|
|
28
28
|
b.references(source: "#this") {
|
29
|
-
b.TLCOrganization(
|
30
|
-
b.TLCOrganization(
|
29
|
+
b.TLCOrganization(eId: 'slaw', href: 'https://github.com/longhotsummer/slaw', showAs: "Slaw")
|
30
|
+
b.TLCOrganization(eId: 'council', href: '/ontology/organization/za/council', showAs: "Council")
|
31
31
|
}
|
32
32
|
}
|
33
33
|
end
|
@@ -38,7 +38,7 @@ module Slaw
|
|
38
38
|
b.FRBRWork { |b|
|
39
39
|
b.FRBRthis(value: "#{WORK_URI}/main")
|
40
40
|
b.FRBRuri(value: WORK_URI)
|
41
|
-
b.FRBRalias(value: 'Short Title')
|
41
|
+
b.FRBRalias(value: 'Short Title', name: 'title')
|
42
42
|
b.FRBRdate(date: '1980-01-01', name: 'Generation')
|
43
43
|
b.FRBRauthor(href: '#council')
|
44
44
|
b.FRBRcountry(value: 'za')
|
@@ -125,7 +125,7 @@ module Slaw
|
|
125
125
|
if !stmts.empty?
|
126
126
|
b.preamble { |b|
|
127
127
|
stmts.each { |e|
|
128
|
-
e.preamble_statement.to_xml(b, "")
|
128
|
+
e.preamble_statement.to_xml(b, "preamble__")
|
129
129
|
}
|
130
130
|
}
|
131
131
|
end
|
@@ -138,11 +138,11 @@ module Slaw
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def to_xml(b, id_prefix='', *args)
|
141
|
-
id = id_prefix + "
|
141
|
+
id = id_prefix + "part_#{Slaw::Grammars::Counters.clean(num)}"
|
142
142
|
|
143
|
-
b.part(
|
143
|
+
b.part(eId: id) { |b|
|
144
144
|
heading.to_xml(b)
|
145
|
-
children.elements.each_with_index { |e, i| e.to_xml(b, id + '
|
145
|
+
children.elements.each_with_index { |e, i| e.to_xml(b, id + '__', i) }
|
146
146
|
}
|
147
147
|
end
|
148
148
|
end
|
@@ -171,13 +171,15 @@ module Slaw
|
|
171
171
|
num = self.num
|
172
172
|
if num.empty?
|
173
173
|
num = Slaw::Grammars::Counters.counters[id_prefix]['subpart'] += 1
|
174
|
+
else
|
175
|
+
num = Slaw::Grammars::Counters.clean(num)
|
174
176
|
end
|
175
177
|
|
176
|
-
id = id_prefix + "
|
178
|
+
id = id_prefix + "subpart_#{num}"
|
177
179
|
|
178
|
-
b.subpart(
|
180
|
+
b.subpart(eId: id) { |b|
|
179
181
|
heading.to_xml(b)
|
180
|
-
children.elements.each_with_index { |e, i| e.to_xml(b, id + '
|
182
|
+
children.elements.each_with_index { |e, i| e.to_xml(b, id + '__', i) }
|
181
183
|
}
|
182
184
|
end
|
183
185
|
end
|
@@ -203,11 +205,11 @@ module Slaw
|
|
203
205
|
end
|
204
206
|
|
205
207
|
def to_xml(b, id_prefix='', *args)
|
206
|
-
id = id_prefix + "
|
208
|
+
id = id_prefix + "chp_#{Slaw::Grammars::Counters.clean(num)}"
|
207
209
|
|
208
|
-
b.chapter(
|
210
|
+
b.chapter(eId: id) { |b|
|
209
211
|
heading.to_xml(b)
|
210
|
-
children.elements.each_with_index { |e, i| e.to_xml(b, id + '
|
212
|
+
children.elements.each_with_index { |e, i| e.to_xml(b, id + '__', i) }
|
211
213
|
}
|
212
214
|
end
|
213
215
|
end
|
@@ -233,11 +235,11 @@ module Slaw
|
|
233
235
|
end
|
234
236
|
|
235
237
|
def to_xml(b, *args)
|
236
|
-
id = "
|
237
|
-
b.section(
|
238
|
+
id = "sec_#{Slaw::Grammars::Counters.clean(num)}"
|
239
|
+
b.section(eId: id) { |b|
|
238
240
|
section_title.to_xml(b)
|
239
241
|
|
240
|
-
idprefix = "#{id}
|
242
|
+
idprefix = "#{id}__"
|
241
243
|
children.elements.each_with_index { |e, i| e.to_xml(b, idprefix, i) }
|
242
244
|
}
|
243
245
|
end
|
@@ -308,11 +310,11 @@ module Slaw
|
|
308
310
|
|
309
311
|
class BlockElements < Treetop::Runtime::SyntaxNode
|
310
312
|
def to_xml(b, idprefix='', i=0)
|
311
|
-
cnt = Slaw::Grammars::Counters.counters[idprefix]['
|
312
|
-
id = "#{idprefix}
|
313
|
-
idprefix = "#{id}
|
313
|
+
cnt = Slaw::Grammars::Counters.counters[idprefix]['hcontainer'] += 1
|
314
|
+
id = "#{idprefix}hcontainer_#{cnt}"
|
315
|
+
idprefix = "#{id}__"
|
314
316
|
|
315
|
-
b.
|
317
|
+
b.hcontainer(eId: id) { |b|
|
316
318
|
b.content { |b|
|
317
319
|
elements.each_with_index { |e, i| e.to_xml(b, idprefix, i) }
|
318
320
|
}
|
@@ -326,10 +328,10 @@ module Slaw
|
|
326
328
|
end
|
327
329
|
|
328
330
|
def to_xml(b, idprefix, i)
|
329
|
-
id = idprefix +
|
330
|
-
idprefix = id + "
|
331
|
+
id = idprefix + "subsec_" + Slaw::Grammars::Counters.clean(num)
|
332
|
+
idprefix = id + "__"
|
331
333
|
|
332
|
-
b.subsection(
|
334
|
+
b.subsection(eId: id) { |b|
|
333
335
|
b.num(num)
|
334
336
|
block_elements_with_inline.to_xml(b, idprefix)
|
335
337
|
}
|
@@ -341,10 +343,10 @@ module Slaw
|
|
341
343
|
# yield to it a builder to insert a listIntroduction node
|
342
344
|
def to_xml(b, idprefix, i=0, &block)
|
343
345
|
cnt = Slaw::Grammars::Counters.counters[idprefix]['list'] += 1
|
344
|
-
id = idprefix + "
|
345
|
-
idprefix = id + '
|
346
|
+
id = idprefix + "list_#{cnt}"
|
347
|
+
idprefix = id + '__'
|
346
348
|
|
347
|
-
b.blockList(
|
349
|
+
b.blockList(eId: id, renest: true) { |b|
|
348
350
|
b.listIntroduction { |b| yield b } if block_given?
|
349
351
|
|
350
352
|
elements.each { |e| e.to_xml(b, idprefix) }
|
@@ -358,7 +360,7 @@ module Slaw
|
|
358
360
|
end
|
359
361
|
|
360
362
|
def to_xml(b, idprefix)
|
361
|
-
b.item(
|
363
|
+
b.item(eId: idprefix + "item_" + Slaw::Grammars::Counters.clean(num)) { |b|
|
362
364
|
b.num(num)
|
363
365
|
b.p { |b|
|
364
366
|
item_content.inline_items.to_xml(b, idprefix) if respond_to? :item_content and item_content.respond_to? :inline_items
|
@@ -369,10 +371,10 @@ module Slaw
|
|
369
371
|
|
370
372
|
class Crossheading < Treetop::Runtime::SyntaxNode
|
371
373
|
def to_xml(b, idprefix, i=0)
|
372
|
-
cnt = Slaw::Grammars::Counters.counters[idprefix]['
|
373
|
-
id = "#{idprefix}
|
374
|
+
cnt = Slaw::Grammars::Counters.counters[idprefix]['hcontainer'] += 1
|
375
|
+
id = "#{idprefix}hcontainer_#{cnt}"
|
374
376
|
|
375
|
-
b.hcontainer(
|
377
|
+
b.hcontainer(eId: id, name: 'crossheading') { |b|
|
376
378
|
b.heading { |b|
|
377
379
|
inline_items.to_xml(b, idprefix)
|
378
380
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0"?>
|
2
2
|
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
3
|
-
xmlns:a="http://
|
3
|
+
xmlns:a="http://docs.oasis-open.org/legaldocml/ns/akn/3.0"
|
4
4
|
exclude-result-prefixes="a">
|
5
5
|
|
6
6
|
<xsl:output method="text" indent="no" omit-xml-declaration="yes" />
|
@@ -42,6 +42,7 @@
|
|
42
42
|
<xsl:apply-templates select="a:preamble" />
|
43
43
|
<xsl:apply-templates select="a:body" />
|
44
44
|
<xsl:apply-templates select="a:conclusions" />
|
45
|
+
<xsl:apply-templates select="a:attachments/a:attachment" />
|
45
46
|
</xsl:template>
|
46
47
|
|
47
48
|
<xsl:template match="a:preface">
|
@@ -163,9 +164,8 @@
|
|
163
164
|
</xsl:template>
|
164
165
|
|
165
166
|
|
166
|
-
<!--
|
167
|
-
|
168
|
-
<xsl:template match="a:hcontainer[@name='schedule']">
|
167
|
+
<!-- attachments/schedules -->
|
168
|
+
<xsl:template match="a:attachment">
|
169
169
|
<xsl:text>SCHEDULE HEADING </xsl:text>
|
170
170
|
<xsl:apply-templates select="a:heading" />
|
171
171
|
<xsl:text> </xsl:text>
|
@@ -177,24 +177,7 @@
|
|
177
177
|
</xsl:if>
|
178
178
|
|
179
179
|
<xsl:text> </xsl:text>
|
180
|
-
<xsl:apply-templates select="
|
181
|
-
</xsl:template>
|
182
|
-
|
183
|
-
|
184
|
-
<!-- old-style schedules, "article" elements -->
|
185
|
-
<xsl:template match="a:doc/a:mainBody/a:article">
|
186
|
-
<xsl:text>SCHEDULE HEADING </xsl:text>
|
187
|
-
<xsl:value-of select="../../a:meta/a:identification/a:FRBRWork/a:FRBRalias/@value" />
|
188
|
-
<xsl:text> </xsl:text>
|
189
|
-
|
190
|
-
<xsl:if test="a:heading">
|
191
|
-
<xsl:text>SUBHEADING </xsl:text>
|
192
|
-
<xsl:apply-templates select="a:heading" />
|
193
|
-
<xsl:text> </xsl:text>
|
194
|
-
</xsl:if>
|
195
|
-
|
196
|
-
<xsl:text> </xsl:text>
|
197
|
-
<xsl:apply-templates select="./*[not(self::a:heading)]"/>
|
180
|
+
<xsl:apply-templates select="a:doc/a:mainBody" />
|
198
181
|
</xsl:template>
|
199
182
|
|
200
183
|
|
@@ -203,7 +186,7 @@
|
|
203
186
|
<xsl:text>{| </xsl:text>
|
204
187
|
|
205
188
|
<!-- attributes -->
|
206
|
-
<xsl:for-each select="@*[local-name()!='
|
189
|
+
<xsl:for-each select="@*[local-name()!='eId']">
|
207
190
|
<xsl:value-of select="local-name(.)" />
|
208
191
|
<xsl:text>="</xsl:text>
|
209
192
|
<xsl:value-of select="." />
|
data/lib/slaw/namespace.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
module Slaw
|
2
|
-
|
3
|
-
|
2
|
+
AKN3_NS = 'http://docs.oasis-open.org/legaldocml/ns/akn/3.0'
|
3
|
+
|
4
|
+
@@ns = AKN3_NS
|
5
|
+
|
6
|
+
def self.akn_namespace
|
7
|
+
@@ns
|
4
8
|
end
|
5
9
|
|
6
|
-
|
10
|
+
def self.akn_namespace=(ns)
|
11
|
+
@@ns = ns
|
12
|
+
end
|
7
13
|
end
|
@@ -1,7 +1,8 @@
|
|
1
|
+
require 'slaw/grammars/counters'
|
2
|
+
|
1
3
|
module Slaw
|
2
4
|
module Parse
|
3
5
|
module Blocklists
|
4
|
-
include Slaw::Namespace
|
5
6
|
|
6
7
|
def self.adjust_blocklists(doc)
|
7
8
|
nest_blocklists(doc)
|
@@ -40,9 +41,9 @@ module Slaw
|
|
40
41
|
#
|
41
42
|
# @param doc [Nokogiri::XML::Document] the document
|
42
43
|
def self.nest_blocklists(doc)
|
43
|
-
doc.xpath('//a:blockList[@renest]', a:
|
44
|
+
doc.xpath('//a:blockList[@renest]', a: Slaw.akn_namespace).each do |blocklist|
|
44
45
|
blocklist.remove_attribute('renest')
|
45
|
-
items = blocklist.xpath('a:item', a:
|
46
|
+
items = blocklist.xpath('a:item', a: Slaw.akn_namespace)
|
46
47
|
nest_blocklist_items(items.to_a, guess_number_format(items.first), nil, nil) unless items.empty?
|
47
48
|
end
|
48
49
|
end
|
@@ -53,7 +54,7 @@ module Slaw
|
|
53
54
|
return if items.empty?
|
54
55
|
item = items.shift
|
55
56
|
|
56
|
-
sublist_count =
|
57
|
+
sublist_count = 1
|
57
58
|
number_format = our_number_format
|
58
59
|
|
59
60
|
while item and item.name == 'item'
|
@@ -78,18 +79,18 @@ module Slaw
|
|
78
79
|
# The blockList is inserted as a child of the sibling just before
|
79
80
|
# +item+, and that sibling's content is moved into the
|
80
81
|
# +listIntroduction+ of the new list.
|
81
|
-
sublist = item.document.create_element('blockList',
|
82
|
+
sublist = item.document.create_element('blockList', eId: prev['eId'] + "__list_#{sublist_count}")
|
82
83
|
sublist_count += 1
|
83
84
|
|
84
85
|
# list intro
|
85
|
-
num = prev.at_xpath('a:num', a:
|
86
|
+
num = prev.at_xpath('a:num', a: Slaw.akn_namespace)
|
86
87
|
if intro = num.next_element
|
87
88
|
intro.name = 'listIntroduction'
|
88
89
|
sublist << intro
|
89
90
|
end
|
90
91
|
|
91
92
|
# make +item+ the first in this list
|
92
|
-
item['
|
93
|
+
item['eId'] = sublist['eId'] + "__item_#{Slaw::Grammars::Counters.clean(item.num)}"
|
93
94
|
sublist << item
|
94
95
|
|
95
96
|
# insert this list as a child of the previous item
|
@@ -112,7 +113,7 @@ module Slaw
|
|
112
113
|
# keep it with this list
|
113
114
|
if list
|
114
115
|
list << item
|
115
|
-
item['
|
116
|
+
item['eId'] = list['eId'] + "__item_#{Slaw::Grammars::Counters.clean(item.num)}"
|
116
117
|
end
|
117
118
|
end
|
118
119
|
end
|
@@ -174,7 +175,7 @@ module Slaw
|
|
174
175
|
|
175
176
|
# Change p tags preceding a blocklist into listIntroductions within the blocklist
|
176
177
|
def self.fix_intros(doc)
|
177
|
-
doc.xpath('//a:blockList', a:
|
178
|
+
doc.xpath('//a:blockList', a: Slaw.akn_namespace).each do |blocklist|
|
178
179
|
prev = blocklist.previous
|
179
180
|
if prev and prev.name == 'p'
|
180
181
|
prev.name = 'listIntroduction'
|