slaw 9.2.0 → 10.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://travis-ci.org/longhotsummer/slaw.svg)](http://travis-ci.org/longhotsummer/slaw) [![Gem Version](https://badge.fury.io/rb/slaw.svg)](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'
|