slaw 1.0.0.alpha.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,62 +0,0 @@
1
- require 'slaw/act'
2
-
3
- module Slaw
4
- # An extension of {Slaw::Act} which wraps an AkomaNtoso XML document describing an By-Law.
5
- #
6
- # There are minor differences between Acts and By-laws, the most notable being that a by-law
7
- # is not identified by a year and a number, and therefore has a different FRBR uri structure.
8
- class ByLaw < Act
9
-
10
- # [String] The code of the region this by-law applies to
11
- attr_reader :region
12
-
13
- # [String] A short file-like name of this by-law, unique within its year and region
14
- attr_reader :name
15
-
16
- # ByLaws don't have numbers, use their short-name instead
17
- def num
18
- name
19
- end
20
-
21
- def title
22
- node = @meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRalias', a: NS)
23
- title = node ? node['value'] : "(Unknown)"
24
-
25
- if amended? and not title.end_with?("as amended")
26
- title = title + " as amended"
27
- end
28
-
29
- title
30
- end
31
-
32
- # Set the short (file-like) name for this bylaw. This changes the {#id_uri}.
33
- def name=(value)
34
- @name = value
35
- rebuild_id_uri
36
- end
37
-
38
- # Set the region code for this bylaw. This changes the {#id_uri}.
39
- def region=(value)
40
- @region = value
41
- rebuild_id_uri
42
- end
43
-
44
- protected
45
-
46
- def extract_id_uri
47
- # /za/by-law/cape-town/2010/public-parks
48
-
49
- @id_uri = @meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRuri', a: NS)['value']
50
- empty, @country, @nature, @region, date, @name = @id_uri.split('/')
51
-
52
- # yyyy[-mm-dd]
53
- @year = date.split('-', 2)[0]
54
- end
55
-
56
- def build_id_uri
57
- # /za/by-law/cape-town/2010/public-parks
58
- "/#{@country}/#{@nature}/#{@region}/#{@year}/#{@name}"
59
- end
60
-
61
- end
62
- end
@@ -1,60 +0,0 @@
1
- require 'forwardable'
2
-
3
- module Slaw
4
- # A collection of Act instances.
5
- #
6
- # This is useful for looking up acts by their FRBR uri and for
7
- # loading a collection of XML act documents.
8
- #
9
- # This collection is enumerable and can be iterated over. Use {#items} to
10
- # access the underlying array of objects.
11
- #
12
- # @example Load a collection of acts and then iterate over them.
13
- #
14
- # acts = Slaw::DocumentCollection.new
15
- # acts.discover('/path/to/acts/')
16
- #
17
- # for act in acts
18
- # puts act.short_name
19
- # end
20
- #
21
- class DocumentCollection
22
-
23
- include Enumerable
24
- extend Forwardable
25
-
26
- # [Array<Act>] The underlying array of acts
27
- attr_accessor :items
28
-
29
- def_delegators :items, :each, :<<, :length
30
-
31
- def initialize(items=nil)
32
- @items = items || []
33
- end
34
-
35
- # Find all XML files in `path` and add them into this
36
- # collection.
37
- #
38
- # @param path [String] the path to glob for xml files
39
- # @param cls [Class] the class to instantiate for each file
40
- #
41
- # @return [DocumentCollection] this collection
42
- def discover(path, cls=Slaw::Act)
43
- for fname in Dir.glob("#{path}/**/*.xml")
44
- @items << cls.new(fname)
45
- end
46
-
47
- self
48
- end
49
-
50
- # Try to find an act who's FRBRuri matches this one,
51
- # returning nil on failure
52
- #
53
- # @param uri [String] the uri to look for
54
- #
55
- # @return [Act, nil] the act, or nil
56
- def for_uri(uri)
57
- return @items.find { |doc| doc.id_uri == uri }
58
- end
59
- end
60
- end
@@ -1,23 +0,0 @@
1
- module Slaw
2
- # An event in the lifecycle of an act
3
- class LifecycleEvent
4
- include Slaw::Namespace
5
-
6
- # Date of the event
7
- attr_accessor :date
8
-
9
- # type of the event
10
- attr_accessor :type
11
-
12
- # the source of the event, an XML reference element
13
- attr_accessor :source
14
-
15
- def initialize(element)
16
- @date = element['date']
17
- @type = element['type']
18
-
19
- source_id = element['source'][1..-1]
20
- @source = element.document.at_xpath("//a:references/*[@id=\"#{source_id}\"]", a: NS)
21
- end
22
- end
23
- end
@@ -1,70 +0,0 @@
1
- module Slaw
2
- module Render
3
-
4
- # Support for transforming XML AN documents into HTML.
5
- #
6
- # This rendering is done using XSLT stylesheets. Both an entire
7
- # document and fragments can be rendered.
8
- class HTMLRenderer
9
-
10
- # [Hash] A Hash of Nokogiri::XSLT objects
11
- attr_accessor :xslt
12
-
13
- def initialize
14
- here = File.dirname(__FILE__)
15
-
16
- @xslt = {
17
- act: Nokogiri::XSLT(File.open(File.join([here, 'xsl/act.xsl']))),
18
- fragment: Nokogiri::XSLT(File.open(File.join([here, 'xsl/fragment.xsl']))),
19
- }
20
- end
21
-
22
- # Transform an entire XML document (a Nokogiri::XML::Document object) into HTML.
23
- # Specify `base_url` to manage the base for relative URLs generated by
24
- # the transform.
25
- #
26
- # @param doc [Nokogiri::XML::Document] document to render
27
- # @param base_url [String] root URL for relative URLs (cannot be empty)
28
- #
29
- # @return [String]
30
- def render(doc, base_url='')
31
- params = _transform_params({'base_url' => base_url})
32
- _run_xslt(:act, doc, params)
33
- end
34
-
35
- # Transform just a single node and its children into HTML.
36
- #
37
- # If +elem+ has an id, we use xpath to tell the XSLT which
38
- # element to transform. Otherwise we copy the node into a new
39
- # tree and apply the XSLT to that.
40
- #
41
- # @param node [Nokogiri::XML::Node] node to render
42
- # @param base_url [String] root URL for relative URLs (cannot be empty)
43
- #
44
- # @return [String]
45
- def render_node(node, base_url='')
46
- params = _transform_params({'base_url' => base_url})
47
-
48
- if node.id
49
- params += ['root_elem', "//*[@id='#{node.id}']"]
50
- doc = node.document
51
- else
52
- # create a new document with just this element at the root
53
- doc = Nokogiri::XML::Document.new
54
- doc.root = node
55
- params += ['root_elem', '*']
56
- end
57
-
58
- _run_xslt(:fragment, doc, params)
59
- end
60
-
61
- def _run_xslt(xslt, doc, params)
62
- @xslt[xslt].transform(doc, params).to_s
63
- end
64
-
65
- def _transform_params(params)
66
- Nokogiri::XSLT.quote_params(params)
67
- end
68
- end
69
- end
70
- end
@@ -1,15 +0,0 @@
1
- <?xml version="1.0"?>
2
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
3
- xmlns:a="http://www.akomantoso.org/2.0"
4
- exclude-result-prefixes="a">
5
-
6
- <xsl:import href="elements.xsl" />
7
-
8
- <xsl:output method="html" />
9
-
10
- <xsl:template match="/">
11
- <xsl:apply-templates select="a:akomaNtoso/a:act" />
12
- </xsl:template>
13
-
14
- </xsl:stylesheet>
15
-
@@ -1,120 +0,0 @@
1
- <?xml version="1.0"?>
2
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
3
- xmlns:a="http://www.akomantoso.org/2.0"
4
- exclude-result-prefixes="a">
5
-
6
- <xsl:template match="a:act">
7
- <xsl:element name="span" namespace="">
8
- <xsl:attribute name="class">an-act</xsl:attribute>
9
- <xsl:apply-templates select="a:preamble" />
10
- <xsl:apply-templates select="a:body/a:part | a:body/a:chapter | a:body/a:section" />
11
- </xsl:element>
12
- </xsl:template>
13
-
14
- <!-- for parts and chapters, include an easily stylable heading -->
15
- <xsl:template match="a:part">
16
- <div class="an-part" id="{@id}">
17
- <h1>
18
- <xsl:text>Part </xsl:text>
19
- <xsl:value-of select="./a:num" />
20
- <xsl:text> - </xsl:text>
21
- <xsl:value-of select="./a:heading" />
22
- </h1>
23
-
24
- <xsl:apply-templates select="./*[not(self::a:num) and not(self::a:heading)]" />
25
- </div>
26
- </xsl:template>
27
-
28
- <xsl:template match="a:chapter">
29
- <div class="an-chapter" id="{@id}">
30
- <h1>
31
- <xsl:text>Chapter </xsl:text>
32
- <xsl:value-of select="./a:num" />
33
- <br/>
34
- <xsl:value-of select="./a:heading" />
35
- </h1>
36
-
37
- <xsl:apply-templates select="./*[not(self::a:num) and not(self::a:heading)]" />
38
- </div>
39
- </xsl:template>
40
-
41
- <!-- the schedules "chapter" isn't actually a chapter -->
42
- <xsl:template match="a:chapter[starts-with(@id, 'schedule')]">
43
- <div class="an-chapter" id="{@id}">
44
- <h1>
45
- <xsl:text>Schedule </xsl:text>
46
- <xsl:value-of select="./a:num" />
47
- <br/>
48
- <xsl:value-of select="./a:heading" />
49
- </h1>
50
-
51
- <xsl:apply-templates select="./*[not(self::a:num) and not(self::a:heading)]" />
52
- </div>
53
- </xsl:template>
54
-
55
- <xsl:template match="a:section">
56
- <div class="an-{local-name()}" id="{@id}">
57
- <h3>
58
- <xsl:value-of select="./a:num" />
59
- <xsl:text> </xsl:text>
60
- <xsl:value-of select="./a:heading" />
61
- </h3>
62
-
63
- <xsl:apply-templates select="./*[not(self::a:num) and not(self::a:heading)]" />
64
- </div>
65
- </xsl:template>
66
-
67
- <xsl:template match="a:subsection">
68
- <span class="an-{local-name()}" id="{@id}">
69
- <xsl:apply-templates select="./*[not(self::a:heading)]" />
70
- </span>
71
- </xsl:template>
72
-
73
- <!-- for term nodes, ensure we keep the refersTo element -->
74
- <xsl:template match="a:term">
75
- <a class="an-{local-name()}">
76
- <xsl:attribute name="data-refers-to">
77
- <xsl:value-of select="@refersTo" />
78
- </xsl:attribute>
79
-
80
- <xsl:attribute name="href"><xsl:value-of select="$base_url" />/definitions/#def-<xsl:value-of select="translate(@refersTo, '#', '')" /></xsl:attribute>
81
-
82
- <xsl:apply-templates />
83
- </a>
84
- </xsl:template>
85
-
86
- <!-- for all nodes, generate a SPAN element with a class matching
87
- the AN name of the node and copy over the ID if it exists -->
88
- <xsl:template match="*">
89
- <span class="an-{local-name()}">
90
- <xsl:if test="@id">
91
- <xsl:attribute name="id">
92
- <xsl:value-of select="@id" />
93
- </xsl:attribute>
94
- </xsl:if>
95
- <xsl:apply-templates />
96
- </span>
97
- </xsl:template>
98
-
99
- <!-- For HTML table elements, copy them over then apply normal AN
100
- processing to their contents -->
101
- <xsl:template match="a:table | a:tr | a:th | a:td">
102
- <xsl:element name="{local-name()}">
103
- <xsl:copy-of select="@*" />
104
- <xsl:apply-templates />
105
- </xsl:element>
106
- </xsl:template>
107
-
108
- <!-- special HTML elements -->
109
- <xsl:template match="a:a | a:abbr | a:b | a:i | a:span | a:sub | a:sup | a:u">
110
- <xsl:element name="{local-name()}">
111
- <xsl:copy-of select="@*" />
112
- <xsl:apply-templates />
113
- </xsl:element>
114
- </xsl:template>
115
-
116
- <xsl:template match="a:eol">
117
- <xsl:element name="br" />
118
- </xsl:template>
119
-
120
- </xsl:stylesheet>
@@ -1,16 +0,0 @@
1
- <?xml version="1.0"?>
2
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
3
- xmlns:a="http://www.akomantoso.org/2.0"
4
- exclude-result-prefixes="a">
5
-
6
- <xsl:import href="elements.xsl" />
7
-
8
- <xsl:output method="html" />
9
-
10
- <xsl:template match="/">
11
- <!-- root_elem is passed in as an xpath parameter -->
12
- <xsl:apply-templates select="$root_elem" />
13
- </xsl:template>
14
-
15
- </xsl:stylesheet>
16
-
@@ -1,56 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'spec_helper'
4
- require 'slaw'
5
-
6
- describe Slaw::Act do
7
- let(:filename) { File.dirname(__FILE__) + "/fixtures/community-fire-safety.xml" }
8
- subject { Slaw::Act.new(filename) }
9
-
10
- it 'should have correct basic properties' do
11
- subject.title.should == 'Community Fire Safety By-law'
12
- subject.amended?.should be_true
13
- end
14
-
15
- it 'should set the title correctly' do
16
- subject.title = 'foo'
17
- subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRalias', a: Slaw::NS)['value'].should == 'foo'
18
- end
19
-
20
- it 'should set the title if it doesnt exist' do
21
- subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRalias', a: Slaw::NS).remove
22
- subject.title = 'bar'
23
- subject.title.should == 'bar'
24
- end
25
-
26
- it 'should set the publication details' do
27
- subject.meta.at_xpath('./a:publication', a: Slaw::NS).remove
28
-
29
- subject.published!(name: 'foo', number: '1234', date: '2014-01-01')
30
- subject.publication['name'].should == 'foo'
31
- subject.publication['showAs'].should == 'foo'
32
- subject.publication['number'].should == '1234'
33
- end
34
-
35
- it 'should get/set the work date' do
36
- subject.date.should == '2002-02-28'
37
-
38
- subject.date = '2014-01-01'
39
- subject.date.should == '2014-01-01'
40
- subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRdate[@name="Generation"]', a: Slaw::NS)['date'].should == '2014-01-01'
41
- subject.meta.at_xpath('./a:identification/a:FRBRExpression/a:FRBRdate[@name="Generation"]', a: Slaw::NS)['date'].should == '2014-01-01'
42
-
43
- subject.id_uri.should == '/za/by-law/2014/2002'
44
- end
45
-
46
- it 'should update the uri when the year changes' do
47
- subject.id_uri.should == '/za/by-law/cape-town/2002/community-fire-safety'
48
- subject.year = '1980'
49
- subject.id_uri.should == '/za/by-law/1980/2002'
50
- end
51
-
52
- it 'should validate' do
53
- subject.validate.should == []
54
- subject.validates?.should be_true
55
- end
56
- end
@@ -1,49 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'spec_helper'
4
- require 'slaw'
5
-
6
- describe Slaw::ByLaw do
7
- let(:filename) { File.dirname(__FILE__) + "/fixtures/community-fire-safety.xml" }
8
- subject { Slaw::ByLaw.new(filename) }
9
-
10
- it 'should have correct basic properties' do
11
- subject.title.should == 'Community Fire Safety By-law as amended'
12
- subject.amended?.should be_true
13
- end
14
-
15
- it 'should update the uri when the region changes' do
16
- subject.id_uri.should == '/za/by-law/cape-town/2002/community-fire-safety'
17
- subject.region = 'foo-bar'
18
- subject.id_uri.should == '/za/by-law/foo-bar/2002/community-fire-safety'
19
- end
20
-
21
- it 'should update the uri when the name changes' do
22
- subject.id_uri.should == '/za/by-law/cape-town/2002/community-fire-safety'
23
- subject.name = 'foo-bar'
24
- subject.id_uri.should == '/za/by-law/cape-town/2002/foo-bar'
25
- end
26
-
27
- it 'should set the title if it doesnt exist' do
28
- subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRalias', a: Slaw::NS).remove
29
- subject.title = 'bar'
30
- subject.title.should == 'bar as amended'
31
- end
32
-
33
- it 'should get/set the work date' do
34
- subject.date.should == '2002-02-28'
35
-
36
- subject.date = '2014-01-01'
37
- subject.date.should == '2014-01-01'
38
- subject.meta.at_xpath('./a:identification/a:FRBRWork/a:FRBRdate[@name="Generation"]', a: Slaw::NS)['date'].should == '2014-01-01'
39
- subject.meta.at_xpath('./a:identification/a:FRBRExpression/a:FRBRdate[@name="Generation"]', a: Slaw::NS)['date'].should == '2014-01-01'
40
-
41
- subject.id_uri.should == '/za/by-law/cape-town/2014/community-fire-safety'
42
- end
43
-
44
- it 'should update the uri when the year changes' do
45
- subject.id_uri.should == '/za/by-law/cape-town/2002/community-fire-safety'
46
- subject.year = '1980'
47
- subject.id_uri.should == '/za/by-law/cape-town/1980/community-fire-safety'
48
- end
49
- end