om 1.0.2 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.textile +14 -0
- data/VERSION +1 -1
- data/lib/om/samples/mods_article.rb +6 -2
- data/lib/om/xml.rb +0 -9
- data/lib/om/xml/node_generator.rb +7 -0
- data/lib/om/xml/term.rb +3 -0
- data/lib/om/xml/term_value_operators.rb +8 -2
- data/lib/om/xml/term_xpath_generator.rb +58 -29
- data/om.gemspec +2 -14
- data/spec/fixtures/mods_articles/hydrangea_article1.xml +3 -0
- data/spec/unit/document_spec.rb +5 -1
- data/spec/unit/term_value_operators_spec.rb +13 -2
- data/spec/unit/term_xpath_generator_spec.rb +11 -1
- data/spec/unit/terminology_spec.rb +6 -1
- data/spec/unit/xml_spec.rb +0 -3
- metadata +3 -15
- data/lib/om/xml/accessors.rb +0 -217
- data/lib/om/xml/generator.rb +0 -26
- data/lib/om/xml/properties.rb +0 -396
- data/lib/om/xml/property_value_operators.rb +0 -160
- data/spec/unit/accessors_spec.rb +0 -216
- data/spec/unit/generator_spec.rb +0 -67
- data/spec/unit/properties_spec.rb +0 -315
- data/spec/unit/property_value_operators_spec.rb +0 -399
@@ -1,160 +0,0 @@
|
|
1
|
-
require "open-uri"
|
2
|
-
require "logger"
|
3
|
-
|
4
|
-
class OM::XML::ParentNodeNotFoundError < RuntimeError; end
|
5
|
-
module OM::XML::PropertyValueOperators
|
6
|
-
|
7
|
-
def property_values(*lookup_args)
|
8
|
-
result = []
|
9
|
-
retrieve(*lookup_args).each {|node| result << node.text }
|
10
|
-
return result
|
11
|
-
end
|
12
|
-
|
13
|
-
#
|
14
|
-
# example properties values hash: {[{":person"=>"0"}, "role", "text"]=>{"0"=>"role1", "1"=>"role2", "2"=>"role3"}, [{:person=>1}, :family_name]=>"Andronicus", [{"person"=>"1"},:given_name]=>["Titus"],[{:person=>1},:role,:text]=>["otherrole1","otherrole2"] }
|
15
|
-
def update_properties(params={})
|
16
|
-
# remove any fields from params that this datastream doesn't recognize
|
17
|
-
params.delete_if do |field_key,new_values|
|
18
|
-
if field_key.kind_of?(String)
|
19
|
-
true
|
20
|
-
else
|
21
|
-
self.class.accessor_xpath(*OM.destringify(field_key) ).nil?
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
result = params.dup
|
26
|
-
|
27
|
-
params.each_pair do |property_pointer,new_values|
|
28
|
-
pointer = OM.destringify(property_pointer)
|
29
|
-
template = OM.pointers_to_flat_array(pointer,false)
|
30
|
-
hn = self.class.accessor_hierarchical_name(*pointer)
|
31
|
-
|
32
|
-
case new_values
|
33
|
-
when Hash
|
34
|
-
when Array
|
35
|
-
nv = new_values.dup
|
36
|
-
new_values = {}
|
37
|
-
nv.each {|v| new_values[nv.index(v).to_s] = v}
|
38
|
-
else
|
39
|
-
new_values = {"0"=>new_values}
|
40
|
-
end
|
41
|
-
|
42
|
-
result.delete(property_pointer)
|
43
|
-
result[hn] = new_values.dup
|
44
|
-
|
45
|
-
current_values = property_values(*pointer)
|
46
|
-
new_values.delete_if do |y,z|
|
47
|
-
if current_values[y.to_i]==z and y.to_i > -1
|
48
|
-
true
|
49
|
-
else
|
50
|
-
false
|
51
|
-
end
|
52
|
-
end
|
53
|
-
xpath = self.class.accessor_xpath(*pointer)
|
54
|
-
parent_pointer = pointer.dup
|
55
|
-
parent_pointer.pop
|
56
|
-
parent_xpath = self.class.accessor_xpath(*parent_pointer)
|
57
|
-
new_values.each do |y,z|
|
58
|
-
if retrieve(*pointer)[y.to_i].nil? || y.to_i == -1
|
59
|
-
result[hn].delete(y)
|
60
|
-
property_values_append(:parent_select=>parent_xpath,:child_index=>0,:template=>template,:values=>z)
|
61
|
-
new_array_index = retrieve(*pointer).length - 1
|
62
|
-
result[hn][new_array_index.to_s] = z
|
63
|
-
else
|
64
|
-
property_value_update(xpath, y.to_i, z)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
# current_values.delete_if {|x| x == :delete || x == "" || x == nil}
|
68
|
-
# instance_eval("#{field_accessor_method}=(current_values)") #write it back to the ds
|
69
|
-
# result[field_name].delete("-1")
|
70
|
-
end
|
71
|
-
return result
|
72
|
-
end
|
73
|
-
|
74
|
-
def property_values_append(opts={})
|
75
|
-
parent_select = Array( opts[:parent_select] )
|
76
|
-
child_index = opts[:child_index]
|
77
|
-
template = opts[:template]
|
78
|
-
new_values = Array( opts[:values] )
|
79
|
-
|
80
|
-
# If template is a string, use it as the template, otherwise use it as arguments to builder_template
|
81
|
-
unless template.instance_of?(String)
|
82
|
-
template_args = Array(template)
|
83
|
-
if template_args.last.kind_of?(Hash)
|
84
|
-
template_opts = template_args.delete_at(template_args.length - 1)
|
85
|
-
else
|
86
|
-
template_opts = {}
|
87
|
-
end
|
88
|
-
template = self.class.builder_template( template_args, template_opts )
|
89
|
-
end
|
90
|
-
|
91
|
-
parent_nodeset = lookup(parent_select[0], parent_select[1])
|
92
|
-
parent_node = node_from_set(parent_nodeset, child_index)
|
93
|
-
|
94
|
-
if parent_node.nil?
|
95
|
-
raise OM::XML::ParentNodeNotFoundError, "Failed to find a parent node to insert values into based on :parent_select #{parent_select.inspect} with :child_index #{child_index.inspect}"
|
96
|
-
end
|
97
|
-
|
98
|
-
builder = Nokogiri::XML::Builder.with(parent_node) do |xml|
|
99
|
-
new_values.each do |builder_new_value|
|
100
|
-
builder_arg = eval('"'+ template + '"') # this inserts builder_new_value into the builder template
|
101
|
-
eval(builder_arg)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
# Nokogiri::XML::Node.new(builder.to_xml, foo)
|
106
|
-
|
107
|
-
return parent_node
|
108
|
-
|
109
|
-
end
|
110
|
-
|
111
|
-
def property_value_update(node_select,child_index,new_value,opts={})
|
112
|
-
# template = opts.fetch(:template,nil)
|
113
|
-
node = lookup(node_select, nil)[child_index]
|
114
|
-
node.content = new_value
|
115
|
-
end
|
116
|
-
|
117
|
-
# def property_value_set(property_ref, query_opts, node_index, new_value)
|
118
|
-
# end
|
119
|
-
|
120
|
-
def property_value_delete(opts={})
|
121
|
-
parent_select = Array( opts[:parent_select] )
|
122
|
-
parent_index = opts[:parent_index]
|
123
|
-
child_index = opts[:child_index]
|
124
|
-
xpath_select = opts[:select]
|
125
|
-
|
126
|
-
if !xpath_select.nil?
|
127
|
-
node = lookup(xpath_select, nil).first
|
128
|
-
else
|
129
|
-
parent_nodeset = lookup(parent_select, parent_select)
|
130
|
-
# parent_nodeset = lookup(parent_select[0])
|
131
|
-
|
132
|
-
if parent_index.nil?
|
133
|
-
node = node_from_set(parent_nodeset, child_index)
|
134
|
-
else
|
135
|
-
parent = node_from_set(parent_nodeset, parent_index)
|
136
|
-
# this next line is a hack around the fact that element_children() sometimes doesn't work.
|
137
|
-
node = node_from_set(parent.xpath("*"), child_index)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
node.remove
|
142
|
-
end
|
143
|
-
|
144
|
-
|
145
|
-
# Allows you to provide an array index _or_ a symbol representing the function to call on the nodeset in order to retrieve the node.
|
146
|
-
def node_from_set(nodeset, index)
|
147
|
-
if index.kind_of?(Integer)
|
148
|
-
node = nodeset[index]
|
149
|
-
elsif index.kind_of?(Symbol) && nodeset.respond_to?(index)
|
150
|
-
node = nodeset.send(index)
|
151
|
-
else
|
152
|
-
raise "Could not retrieve node using index #{index}."
|
153
|
-
end
|
154
|
-
|
155
|
-
return node
|
156
|
-
end
|
157
|
-
|
158
|
-
private :node_from_set
|
159
|
-
|
160
|
-
end
|
data/spec/unit/accessors_spec.rb
DELETED
@@ -1,216 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
require "nokogiri"
|
3
|
-
require "om"
|
4
|
-
|
5
|
-
describe "OM::XML::Accessors" do
|
6
|
-
|
7
|
-
before(:all) do
|
8
|
-
class AccessorTest
|
9
|
-
|
10
|
-
include OM::XML::Container
|
11
|
-
include OM::XML::Accessors
|
12
|
-
#accessor :title, :relative_xpath=>[:titleInfo, :title]}}
|
13
|
-
|
14
|
-
accessor :title_info, :relative_xpath=>'oxns:titleInfo', :children=>[
|
15
|
-
{:main_title=>{:relative_xpath=>'oxns:title'}},
|
16
|
-
{:language =>{:relative_xpath=>{:attribute=>"lang"} }}
|
17
|
-
] # this allows you to access the language attribute as if it was a regular child accessor
|
18
|
-
accessor :abstract
|
19
|
-
accessor :topic_tag, :relative_xpath=>'oxns:subject/oxns:topic'
|
20
|
-
accessor :person, :relative_xpath=>'oxns:name[@type="personal"]', :children=>[
|
21
|
-
{:last_name=>{:relative_xpath=>'oxns:namePart[@type="family"]'}},
|
22
|
-
{:first_name=>{:relative_xpath=>'oxns:namePart[@type="given"]'}},
|
23
|
-
{:institution=>{:relative_xpath=>'oxns:affiliation'}},
|
24
|
-
{:role=>{:children=>[
|
25
|
-
{:text=>{:relative_xpath=>'oxns:roleTerm[@type="text"]'}},
|
26
|
-
{:code=>{:relative_xpath=>'oxns:roleTerm[@type="code"]'}}
|
27
|
-
]}}
|
28
|
-
]
|
29
|
-
accessor :organization, :relative_xpath=>'oxns:name[@type="institutional"]', :children=>[
|
30
|
-
{:role=>{:children=>[
|
31
|
-
{:text=>{:relative_xpath=>'oxns:roleTerm[@type="text"]'}},
|
32
|
-
{:code=>{:relative_xpath=>'oxns:roleTerm[@type="code"]'}}
|
33
|
-
]}}
|
34
|
-
]
|
35
|
-
accessor :conference, :relative_xpath=>'oxns:name[@type="conference"]', :children=>[
|
36
|
-
{:role=>{:children=>[
|
37
|
-
{:text=>{:relative_xpath=>'oxns:roleTerm[@type="text"]'}},
|
38
|
-
{:code=>{:relative_xpath=>'oxns:roleTerm[@type="code"]'}}
|
39
|
-
]}}
|
40
|
-
]
|
41
|
-
accessor :journal, :relative_xpath=>'oxns:relatedItem[@type="host"]', :children=>[
|
42
|
-
# allows for children that are hashes...
|
43
|
-
# this allows for more robust handling of nested values (in generating views and when generating solr field names)
|
44
|
-
{:title=>{:relative_xpath=>'oxns:titleInfo/oxns:title'}},
|
45
|
-
{:publisher=>{:relative_xpath=>'oxns:originInfo/oxns:publisher'}},
|
46
|
-
{:issn=>{:relative_xpath=>'oxns:identifier[@type="issn"]'}},
|
47
|
-
{:date_issued=>{:relative_xpath=>'oxns:originInfo/oxns:dateIssued'}},
|
48
|
-
{:issue => {:relative_xpath=>"oxns:part", :children=>[
|
49
|
-
{:volume=>{:relative_xpath=>'oxns:detail[@type="volume"]'}},
|
50
|
-
{:level=>{:relative_xpath=>'oxns:detail[@type="level"]'}},
|
51
|
-
{:start_page=>{:relative_xpath=>'oxns:extent[@unit="pages"]/oxns:start'}},
|
52
|
-
{:end_page=>{:relative_xpath=>'oxns:extent[@unit="pages"]/oxns:end'}},
|
53
|
-
{:publication_date=>{:relative_xpath=>'oxns:date'}}
|
54
|
-
]}}
|
55
|
-
]
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
before(:each) do
|
61
|
-
article_xml = fixture( File.join("mods_articles", "hydrangea_article1.xml") )
|
62
|
-
@sample = AccessorTest.from_xml(article_xml)
|
63
|
-
@sample.stubs(:ox_namespaces).returns("oxns"=>"http://www.loc.gov/mods/v3")
|
64
|
-
end
|
65
|
-
|
66
|
-
describe '#accessor' do
|
67
|
-
it "should populate the .accessors hash" do
|
68
|
-
AccessorTest.accessors[:abstract][:relative_xpath].should == "oxns:abstract"
|
69
|
-
AccessorTest.accessors[:journal][:relative_xpath].should == 'oxns:relatedItem[@type="host"]'
|
70
|
-
AccessorTest.accessors[:journal][:children][:issue][:relative_xpath].should == "oxns:part"
|
71
|
-
AccessorTest.accessors[:journal][:children][:issue][:children][:end_page][:relative_xpath].should == 'oxns:extent[@unit="pages"]/oxns:end'
|
72
|
-
|
73
|
-
AccessorTest.accessors[:person][:children][:role][:children][:text][:relative_xpath].should == 'oxns:roleTerm[@type="text"]'
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
describe ".retrieve" do
|
78
|
-
it "should use Nokogiri to retrieve a NodeSet corresponding to the combination of accessor keys and array/nodeset indexes" do
|
79
|
-
@sample.retrieve( :person ).length.should == 2
|
80
|
-
|
81
|
-
@sample.retrieve( {:person=>1} ).first.should == @sample.ng_xml.xpath('//oxns:name[@type="personal"][2]', "oxns"=>"http://www.loc.gov/mods/v3").first
|
82
|
-
@sample.retrieve( {:person=>1}, :first_name ).class.should == Nokogiri::XML::NodeSet
|
83
|
-
@sample.retrieve( {:person=>1}, :first_name ).first.text.should == "Siddartha"
|
84
|
-
end
|
85
|
-
|
86
|
-
it "should support accessors whose relative_xpath is a lookup array instead of an xpath string" do
|
87
|
-
# pending "this only impacts scenarios where we want to display & edit"
|
88
|
-
AccessorTest.accessors[:title_info][:children][:language][:relative_xpath].should == {:attribute=>"lang"}
|
89
|
-
# @sample.retrieve( :title, 1 ).first.text.should == "Artikkelin otsikko Hydrangea artiklan 1"
|
90
|
-
@sample.retrieve( {:title_info=>1}, :language ).first.text.should == "finnish"
|
91
|
-
end
|
92
|
-
|
93
|
-
it "should support xpath queries as the pointer" do
|
94
|
-
@sample.retrieve('//oxns:name[@type="personal"][1]/oxns:namePart[1]').first.text.should == "FAMILY NAME"
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should return nil if the xpath fails to generate" do
|
98
|
-
@sample.retrieve( {:foo=>20}, :bar ).should == nil
|
99
|
-
end
|
100
|
-
|
101
|
-
end
|
102
|
-
|
103
|
-
describe "generated accessor methods" do
|
104
|
-
it "should mix accessor methods into nodesets so you can use regular array syntax to access stuff" do
|
105
|
-
pending "This is tempting, but somewhat difficult to implement and potentially slow at runtime. Might never be worth it?"
|
106
|
-
@sample.persons.length.should == 2
|
107
|
-
@sample.persons[1].first_name.text.should == "Siddartha"
|
108
|
-
@sample.persons.last.roles.length.should == 1
|
109
|
-
@sample.persons.last.roles[0].text.should == "teacher"
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
describe "#accessor_info" do
|
114
|
-
it "should return the xpath given in the call to #accessor" do
|
115
|
-
AccessorTest.accessor_info( :abstract ).should == AccessorTest.accessors[:abstract]
|
116
|
-
end
|
117
|
-
it "should return the xpath given in the call to #accessor" do
|
118
|
-
AccessorTest.accessor_info( :abstract ).should == AccessorTest.accessors[:abstract]
|
119
|
-
end
|
120
|
-
it "should dig into the accessors hash as far as you want, ignoring index values" do
|
121
|
-
AccessorTest.accessor_info( *[{:conference=>0}, {:role=>1}, :text] ).should == AccessorTest.accessors[:conference][:children][:role][:children][:text]
|
122
|
-
AccessorTest.accessor_info( {:conference=>0}, {:role=>1}, :text ).should == AccessorTest.accessors[:conference][:children][:role][:children][:text]
|
123
|
-
|
124
|
-
AccessorTest.accessor_info( :conference, :role, :text ).should == AccessorTest.accessors[:conference][:children][:role][:children][:text]
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
describe "#accessor_xpath" do
|
129
|
-
it "should return the xpath given in the call to #accessor" do
|
130
|
-
AccessorTest.accessor_xpath( :abstract ).should == '//oxns:abstract'
|
131
|
-
end
|
132
|
-
# Note: Ruby array indexes begin from 0. In xpath queries (which start from 1 instead of 0), this will be translated accordingly.
|
133
|
-
it "should prepend the xpath for any parent nodes, inserting calls to xpath array lookup where necessary" do
|
134
|
-
AccessorTest.accessor_xpath( {:conference=>0}, {:role=>1}, :text ).should == '//oxns:name[@type="conference"][1]/oxns:role[2]/oxns:roleTerm[@type="text"]'
|
135
|
-
end
|
136
|
-
it "should support xpath queries as argument" do
|
137
|
-
AccessorTest.accessor_xpath('//oxns:name[@type="personal"][1]/oxns:namePart').should == '//oxns:name[@type="personal"][1]/oxns:namePart'
|
138
|
-
end
|
139
|
-
it "should return nil if no accessor_info is available" do
|
140
|
-
AccessorTest.accessor_xpath( :sample_undeclared_accessor ).should == nil
|
141
|
-
end
|
142
|
-
it "should be idempotent" do
|
143
|
-
AccessorTest.accessor_xpath( *[{:title_info=>2}, :main_title] ).should == "//oxns:titleInfo[3]/oxns:title"
|
144
|
-
AccessorTest.accessor_xpath( *[{:title_info=>2}, :main_title] ).should == "//oxns:titleInfo[3]/oxns:title"
|
145
|
-
AccessorTest.accessor_xpath( *[{:title_info=>2}, :main_title] ).should == "//oxns:titleInfo[3]/oxns:title"
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
describe "#accessor_constrained_xpath" do
|
150
|
-
it 'should append contains("#{constraint_value}") to query' do
|
151
|
-
# @sample.class.accessor_constrained_xpath_template([:journal, :issn]).should == '//oxns:relatedItem[@type="host"]/oxns:identifier[@type="issn" and contains("#{constraint_value}")]'
|
152
|
-
@sample.class.accessor_constrained_xpath([:journal, :issn], "123-456-ABC").should == '//oxns:relatedItem[@type="host"]/oxns:identifier[@type="issn" and contains(., "123-456-ABC")]'
|
153
|
-
@sample.class.accessor_constrained_xpath([:journal, :title], "My Journal Title").should == '//oxns:relatedItem[@type="host"]/oxns:titleInfo/oxns:title[contains(., "My Journal Title")]'
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
describe "#accessor_generic_name" do
|
158
|
-
it "should generate a generic accessor name based on an array of pointers" do
|
159
|
-
AccessorTest.accessor_generic_name( {:conference=>0}, {:role=>1}, :text ).should == "conference_role_text"
|
160
|
-
AccessorTest.accessor_generic_name( *[{:conference=>0}, {:role=>1}, :text] ).should == "conference_role_text"
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
describe "#accessor_hierarchical_name" do
|
165
|
-
it "should generate a specific accessor name based on an array of pointers and indexes" do
|
166
|
-
AccessorTest.accessor_hierarchical_name( {:conference=>0}, {:role=>1}, :text ).should == "conference_0_role_1_text"
|
167
|
-
AccessorTest.accessor_hierarchical_name( *[{:conference=>0}, {:role=>1}, :text] ).should == "conference_0_role_1_text"
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
describe '#generate_accessors_from_properties' do
|
172
|
-
before(:each) do
|
173
|
-
class AccessorTest2
|
174
|
-
include OM::XML::Accessors
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
it "should generate accessors from the properties hash" do
|
179
|
-
sample_properties_hash = {:abstract=>{:xpath_relative=>"oxns:abstract", :path=>"abstract", :xpath_constrained=>"//oxns:abstract[contains(\\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:abstract", :ref=>:abstract, :convenience_methods=>{}}, :topic_tag=>{:xpath_relative=>"oxns:subject", :path=>"subject", :xpath_constrained=>"//oxns:subject[contains(oxns:topic, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:subject", :ref=>:topic_tag, :default_content_path=>"topic", :convenience_methods=>{}}, :title_info=>{:xpath_relative=>"oxns:titleInfo", :path=>"titleInfo", :xpath_constrained=>"//oxns:titleInfo[contains(\\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:titleInfo", :ref=>:title_info, :convenience_methods=>{:main_title=>{:xpath_relative=>"oxns:title", :path=>"title", :xpath_constrained=>"//oxns:titleInfo[contains(oxns:title, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:titleInfo/oxns:title"}, :language=>{:xpath_relative=>"@lang", :path=>{:attribute=>"lang"}, :xpath_constrained=>"//oxns:titleInfo[contains(@lang, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:titleInfo/@lang"}}}, :person=>{:xpath_relative=>"oxns:name[@type=\"personal\"]", :path=>"name", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart, \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"personal"}, :xpath=>"//oxns:name[@type=\"personal\"]", :ref=>:person, :default_content_path=>"namePart", :subelements=>["namePart", "displayForm", "affiliation", :role, "description"], :convenience_methods=>{:first_name=>{:xpath_relative=>"oxns:namePart[@type=\"given\"]", :path=>"namePart", :attributes=>{:type=>"given"}, :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart[@type=\\\"given\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart[@type=\"given\"]"}, :affiliation=>{:xpath_relative=>"oxns:affiliation", :path=>"affiliation", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:affiliation, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:affiliation"}, :terms_of_address=>{:xpath_relative=>"oxns:namePart[@type=\"termsOfAddress\"]", :path=>"namePart", :attributes=>{:type=>"termsOfAddress"}, :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart[@type=\\\"termsOfAddress\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart[@type=\"termsOfAddress\"]"}, :namePart=>{:xpath_relative=>"oxns:namePart", :path=>"namePart", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart"}, :displayForm=>{:xpath_relative=>"oxns:displayForm", :path=>"displayForm", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:displayForm, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:displayForm"}, :role=>{:xpath_relative=>"oxns:role", :path=>"role", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:role, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:role", :ref=>:role, :convenience_methods=>{:text=>{:xpath_relative=>"oxns:roleTerm[@type=\"text\"]", :path=>"roleTerm", :attributes=>{:type=>"text"}, :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"text\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role/oxns:roleTerm[@type=\"text\"]"}, :code=>{:xpath_relative=>"oxns:roleTerm[@type=\"code\"]", :path=>"roleTerm", :attributes=>{:type=>"code"}, :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"code\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role/oxns:roleTerm[@type=\"code\"]"}}, :parents=>[:name_]}, :date=>{:xpath_relative=>"oxns:namePart[@type=\"date\"]", :path=>"namePart", :attributes=>{:type=>"date"}, :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart[@type=\\\"date\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart[@type=\"date\"]"}, :family_name=>{:xpath_relative=>"oxns:namePart[@type=\"family\"]", :path=>"namePart", :attributes=>{:type=>"family"}, :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:namePart[@type=\\\"family\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:namePart[@type=\"family\"]"}, :description=>{:xpath_relative=>"oxns:description", :path=>"description", :xpath_constrained=>"//oxns:name[@type=\\\"personal\\\" and contains(oxns:description, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name[@type=\"personal\"]/oxns:description"}}, :variant_of=>:name_}, :name_=>{:xpath_relative=>"oxns:name", :path=>"name", :xpath_constrained=>"//oxns:name[contains(oxns:namePart, \\\"\#{constraint_value}\\\")]", :attributes=>[:xlink, :lang, "xml:lang", :script, :transliteration, {:type=>["personal", "enumerated", "corporate"]}], :xpath=>"//oxns:name", :ref=>:name_, :default_content_path=>"namePart", :subelements=>["namePart", "displayForm", "affiliation", :role, "description"], :convenience_methods=>{:affiliation=>{:xpath_relative=>"oxns:affiliation", :path=>"affiliation", :xpath_constrained=>"//oxns:name[contains(oxns:affiliation, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:affiliation"}, :first_name=>{:xpath_relative=>"oxns:namePart[@type=\"given\"]", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart[@type=\\\"given\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"given"}, :xpath=>"//oxns:name/oxns:namePart[@type=\"given\"]"}, :terms_of_address=>{:xpath_relative=>"oxns:namePart[@type=\"termsOfAddress\"]", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart[@type=\\\"termsOfAddress\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"termsOfAddress"}, :xpath=>"//oxns:name/oxns:namePart[@type=\"termsOfAddress\"]"}, :displayForm=>{:xpath_relative=>"oxns:displayForm", :path=>"displayForm", :xpath_constrained=>"//oxns:name[contains(oxns:displayForm, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:displayForm"}, :namePart=>{:xpath_relative=>"oxns:namePart", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:namePart"}, :role=>{:xpath_relative=>"oxns:role", :path=>"role", :xpath_constrained=>"//oxns:name[contains(oxns:role, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:role", :ref=>:role, :convenience_methods=>{:text=>{:xpath_relative=>"oxns:roleTerm[@type=\"text\"]", :path=>"roleTerm", :attributes=>{:type=>"text"}, :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"text\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role/oxns:roleTerm[@type=\"text\"]"}, :code=>{:xpath_relative=>"oxns:roleTerm[@type=\"code\"]", :path=>"roleTerm", :attributes=>{:type=>"code"}, :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"code\\\"], \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role/oxns:roleTerm[@type=\"code\"]"}}, :parents=>[:name_]}, :description=>{:xpath_relative=>"oxns:description", :path=>"description", :xpath_constrained=>"//oxns:name[contains(oxns:description, \\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:name/oxns:description"}, :family_name=>{:xpath_relative=>"oxns:namePart[@type=\"family\"]", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart[@type=\\\"family\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"family"}, :xpath=>"//oxns:name/oxns:namePart[@type=\"family\"]"}, :date=>{:xpath_relative=>"oxns:namePart[@type=\"date\"]", :path=>"namePart", :xpath_constrained=>"//oxns:name[contains(oxns:namePart[@type=\\\"date\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"date"}, :xpath=>"//oxns:name/oxns:namePart[@type=\"date\"]"}}}, :role=>{:xpath_relative=>"oxns:role", :path=>"role", :xpath_constrained=>"//oxns:role[contains(\\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:role", :ref=>:role, :convenience_methods=>{:text=>{:xpath_relative=>"oxns:roleTerm[@type=\"text\"]", :path=>"roleTerm", :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"text\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"text"}, :xpath=>"//oxns:role/oxns:roleTerm[@type=\"text\"]"}, :code=>{:xpath_relative=>"oxns:roleTerm[@type=\"code\"]", :path=>"roleTerm", :xpath_constrained=>"//oxns:role[contains(oxns:roleTerm[@type=\\\"code\\\"], \\\"\#{constraint_value}\\\")]", :attributes=>{:type=>"code"}, :xpath=>"//oxns:role/oxns:roleTerm[@type=\"code\"]"}}, :parents=>[:name_]}, :unresolved=>{}, :mods=>{:xpath_relative=>"oxns:mods", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd", :path=>"mods", :xpath_constrained=>"//oxns:mods[contains(\\\"\#{constraint_value}\\\")]", :attributes=>["id", "version"], :xpath=>"//oxns:mods", :ref=>:mods, :convenience_methods=>{}}}
|
180
|
-
AccessorTest2.stubs(:properties).returns(sample_properties_hash)
|
181
|
-
AccessorTest2.accessors.should be_nil
|
182
|
-
AccessorTest2.generate_accessors_from_properties.should_not be_nil
|
183
|
-
[:mods, :name_, :person, [:person,:first_name],[:person, :role], [:person, :role, :text] ].each do |pointer|
|
184
|
-
puts pointer
|
185
|
-
ai = AccessorTest2.accessor_info(*pointer)
|
186
|
-
ai.should_not be_nil
|
187
|
-
ai[:relative_xpath].should_not be_nil
|
188
|
-
end
|
189
|
-
AccessorTest2.accessor_info(*[:title_info, :language])[:relative_xpath].should == "@lang"
|
190
|
-
end
|
191
|
-
|
192
|
-
end
|
193
|
-
|
194
|
-
# describe ".accessor_xpath (instance method)" do
|
195
|
-
# it "should delegate to the class method" do
|
196
|
-
# AccessorTest.expects(:accessor_xpath).with( [:conference, conference_index, :text_role] )
|
197
|
-
# @sample.accessor_xpath( [:conference, conference_index, :role] )
|
198
|
-
# end
|
199
|
-
# end
|
200
|
-
#
|
201
|
-
# describe "generated catchall xpaths" do
|
202
|
-
# it "should return an xpath query that will catch all nodes corresponding to the specified accessor" do
|
203
|
-
# AccessorTest.journal_issue_end_page_xpath.should == 'oxns:relatedItem[@type="host"]/oxns:part/oxns:extent[@unit="pages"]/oxns:end'
|
204
|
-
# end
|
205
|
-
# it "should rely on #catchall_xpath" do
|
206
|
-
# AccessorTest.expects(:catchall_xpath).with(:journal, :issue, :end_page)
|
207
|
-
# AccessorTest.journal_issue_end_page_xpath
|
208
|
-
# end
|
209
|
-
# end
|
210
|
-
#
|
211
|
-
# describe ".catchall_xpath" do
|
212
|
-
# it "should return an xpath query that will catch all nodes corresponding to the specified accessor" do
|
213
|
-
# AccessorTest.catchall_xpath(:journal, :issue, :end_page).should == 'oxns:relatedItem[@type="host"]/oxns:part/oxns:extent[@unit="pages"]/oxns:end'
|
214
|
-
# end
|
215
|
-
# end
|
216
|
-
end
|
data/spec/unit/generator_spec.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
require "om"
|
3
|
-
|
4
|
-
describe "OM::XML::Generator" do
|
5
|
-
|
6
|
-
before(:all) do
|
7
|
-
#ModsHelpers.name_("Beethoven, Ludwig van", :date=>"1770-1827", :role=>"creator")
|
8
|
-
class GeneratorTest
|
9
|
-
|
10
|
-
include OM::XML::Container
|
11
|
-
include OM::XML::Properties
|
12
|
-
include OM::XML::Generator
|
13
|
-
|
14
|
-
# Could add support for multiple root declarations.
|
15
|
-
# For now, assume that any modsCollections have already been broken up and fed in as individual mods documents
|
16
|
-
# root :mods_collection, :path=>"modsCollection",
|
17
|
-
# :attributes=>[],
|
18
|
-
# :subelements => :mods
|
19
|
-
|
20
|
-
root_property :mods, "mods", "http://www.loc.gov/mods/v3", :attributes=>["id", "version"], :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"
|
21
|
-
|
22
|
-
|
23
|
-
property :name_, :path=>"name",
|
24
|
-
:attributes=>[:xlink, :lang, "xml:lang", :script, :transliteration, {:type=>["personal", "enumerated", "corporate"]} ],
|
25
|
-
:subelements=>["namePart", "displayForm", "affiliation", :role, "description"],
|
26
|
-
:default_content_path => "namePart",
|
27
|
-
:convenience_methods => {
|
28
|
-
:date => {:path=>"namePart", :attributes=>{:type=>"date"}},
|
29
|
-
:family_name => {:path=>"namePart", :attributes=>{:type=>"family"}},
|
30
|
-
:given_name => {:path=>"namePart", :attributes=>{:type=>"given"}},
|
31
|
-
:terms_of_address => {:path=>"namePart", :attributes=>{:type=>"termsOfAddress"}}
|
32
|
-
}
|
33
|
-
property :person, :variant_of=>:name_, :attributes=>{:type=>"personal"}
|
34
|
-
property :role, :path=>"role",
|
35
|
-
:parents=>[:name_],
|
36
|
-
:attributes=>[ { "type"=>["text", "code"] } , "authority"],
|
37
|
-
:default_content_path => "roleTerm"
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
before(:each) do
|
44
|
-
@sample = GeneratorTest.from_xml( fixture( File.join("test_dummy_mods.xml") ) )
|
45
|
-
end
|
46
|
-
|
47
|
-
after(:all) do
|
48
|
-
Object.send(:remove_const, :GeneratorTest)
|
49
|
-
end
|
50
|
-
|
51
|
-
describe '#generate' do
|
52
|
-
it "should use the corresponding builder template(s) to generate the node" do
|
53
|
-
GeneratorTest.generate(:mods, "foo").root.to_xml.should == "<mods>foo</mods>"
|
54
|
-
# GeneratorTest.generate([:person,:role], "creator", {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}}).root.to_xml.should == "<role authority=\"marcrelator\" type=\"code\">\n <roleTerm>creator</roleTerm>\n</role>"
|
55
|
-
generated_node = GeneratorTest.generate([:person,:role], "creator", {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}})
|
56
|
-
# generated_node.should have_node 'role[@authority="marcrelator"][@type="code"]' do
|
57
|
-
# with_node "roleTerm", "creator"
|
58
|
-
# end
|
59
|
-
generated_node.xpath('./role[@authority="marcrelator"][@type="code"]').xpath("./roleTerm").text.should == "creator"
|
60
|
-
|
61
|
-
end
|
62
|
-
it "should return Nokogiri Documents" do
|
63
|
-
GeneratorTest.generate(:mods, "foo").class.should == Nokogiri::XML::Document
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
@@ -1,315 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
require "om"
|
3
|
-
|
4
|
-
describe "OM::XML::Properties" do
|
5
|
-
|
6
|
-
before(:all) do
|
7
|
-
#ModsHelpers.name_("Beethoven, Ludwig van", :date=>"1770-1827", :role=>"creator")
|
8
|
-
class FakeOxMods
|
9
|
-
|
10
|
-
include OM::XML::Container
|
11
|
-
include OM::XML::Properties
|
12
|
-
|
13
|
-
# Could add support for multiple root declarations.
|
14
|
-
# For now, assume that any modsCollections have already been broken up and fed in as individual mods documents
|
15
|
-
# root :mods_collection, :path=>"modsCollection",
|
16
|
-
# :attributes=>[],
|
17
|
-
# :subelements => :mods
|
18
|
-
|
19
|
-
|
20
|
-
root_property :mods, "mods", "http://www.loc.gov/mods/v3", :attributes=>["id", "version"], :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"
|
21
|
-
|
22
|
-
property :title_info, :path=>"titleInfo",
|
23
|
-
:convenience_methods => {
|
24
|
-
:main_title => {:path=>"title"},
|
25
|
-
:language => {:path=>{:attribute=>"lang"}},
|
26
|
-
}
|
27
|
-
|
28
|
-
property :name_, :path=>"name",
|
29
|
-
:attributes=>[:xlink, :lang, "xml:lang", :script, :transliteration, {:type=>["personal", "enumerated", "corporate"]} ],
|
30
|
-
:subelements=>["namePart", "displayForm", "affiliation", :role, "description"],
|
31
|
-
:default_content_path => "namePart",
|
32
|
-
:convenience_methods => {
|
33
|
-
:date => {:path=>"namePart", :attributes=>{:type=>"date"}},
|
34
|
-
:family_name => {:path=>"namePart", :attributes=>{:type=>"family"}},
|
35
|
-
:given_name => {:path=>"namePart", :attributes=>{:type=>"given"}},
|
36
|
-
:terms_of_address => {:path=>"namePart", :attributes=>{:type=>"termsOfAddress"}}
|
37
|
-
}
|
38
|
-
|
39
|
-
property :person, :variant_of=>:name_, :attributes=>{:type=>"personal"}
|
40
|
-
|
41
|
-
property :role, :path=>"role",
|
42
|
-
:parents=>[:name_],
|
43
|
-
:attributes=>[ { "type"=>["text", "code"] } , "authority"],
|
44
|
-
:default_content_path => "roleTerm"
|
45
|
-
|
46
|
-
property :journal, :path=>'relatedItem', :attributes=>{:type=>"host"},
|
47
|
-
:subelements=>[:title_info, :origin_info, :issue],
|
48
|
-
:convenience_methods => {
|
49
|
-
:issn => {:path=>"identifier", :attributes=>{:type=>"issn"}},
|
50
|
-
}
|
51
|
-
|
52
|
-
property :issue, :path=>'part',
|
53
|
-
:subelements=>[:start_page, :end_page, :volume],
|
54
|
-
:convenience_methods => {
|
55
|
-
# :volume => {:path=>"detail", :attributes=>{:type=>"volume"}},
|
56
|
-
:level => {:path=>"detail", :attributes=>{:type=>"number"}, :default_content_path=>"number"},
|
57
|
-
# Hack to support provisional spot for start & end page (nesting was too deep for this version of OM)
|
58
|
-
:citation_start_page => {:path=>"pages", :attributes=>{:type=>"start"}},
|
59
|
-
:citation_end_page => {:path=>"pages", :attributes=>{:type=>"end"}},
|
60
|
-
:foo => {:path=>"foo", :attributes=>{:type=>"ness"}},
|
61
|
-
:publication_date => {:path=>"date"}
|
62
|
-
}
|
63
|
-
|
64
|
-
property :volume, :path=>"detail", :attributes=>{:type=>"volume"}, :subelements=>"number"
|
65
|
-
|
66
|
-
property :start_page, :path=>"extent", :attributes=>{:unit=>"pages"}, :default_content_path => "start"
|
67
|
-
property :end_page, :path=>"extent", :attributes=>{:unit=>"pages"}, :default_content_path => "end"
|
68
|
-
end
|
69
|
-
|
70
|
-
class FakeOtherOx < Nokogiri::XML::Document
|
71
|
-
|
72
|
-
include OM::XML::Properties
|
73
|
-
# extend OX::ClassMethods
|
74
|
-
|
75
|
-
root_property :other, "other", "http://www.foo.com"
|
76
|
-
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
|
81
|
-
before(:each) do
|
82
|
-
@fixturemods = FakeOxMods.from_xml( fixture( File.join("CBF_MODS", "ARS0025_016.xml") ) )
|
83
|
-
end
|
84
|
-
|
85
|
-
after(:all) do
|
86
|
-
Object.send(:remove_const, :FakeOxMods)
|
87
|
-
end
|
88
|
-
|
89
|
-
describe "#new" do
|
90
|
-
it "should set up namespaces" do
|
91
|
-
@fixturemods.ox_namespaces.should == {"oxns"=>"http://www.loc.gov/mods/v3", "xmlns:ns2"=>"http://www.w3.org/1999/xlink", "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance", "xmlns:ns3"=>"http://www.loc.gov/mods/v3"}
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
describe "#root_property" do
|
96
|
-
it "should initialize root_property class attributes without attributes bleeding over to other OX classes" do
|
97
|
-
FakeOxMods.root_property_ref.should == :mods
|
98
|
-
FakeOxMods.root_config.should == {:ref=>:mods, :path=>"mods", :namespace=>"http://www.loc.gov/mods/v3", :attributes=>["id", "version"], :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd"}
|
99
|
-
FakeOxMods.ox_namespaces.should == {"oxns"=>"http://www.loc.gov/mods/v3"}
|
100
|
-
|
101
|
-
FakeOtherOx.root_property_ref.should == :other
|
102
|
-
FakeOtherOx.root_config.should == {:namespace=>"http://www.foo.com", :path=>"other", :ref=>:other}
|
103
|
-
end
|
104
|
-
it "should add a corresponding entry into the properties hash" do
|
105
|
-
FakeOxMods.property_info_for(FakeOxMods.root_property_ref).should == {:schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd", :xpath_relative=>"oxns:mods", :path=>"mods", :xpath_constrained=>"//oxns:mods[contains(\\\"\#{constraint_value}\\\")]", :xpath=>"//oxns:mods", :ref=>:mods, :convenience_methods=>{}, :attributes=>["id", "version"]}
|
106
|
-
FakeOxMods.builder_template(FakeOxMods.root_property_ref).should == "xml.mods( '\#{builder_new_value}' )"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
describe "#property" do
|
111
|
-
|
112
|
-
it "fails gracefully if you try to look up nodes for an undefined property" do
|
113
|
-
@fixturemods.lookup(:nobody_home).should == []
|
114
|
-
end
|
115
|
-
|
116
|
-
it "constructs xpath queries for finding properties" do
|
117
|
-
FakeOxMods.properties[:name_][:xpath].should == '//oxns:name'
|
118
|
-
FakeOxMods.properties[:name_][:xpath_relative].should == 'oxns:name'
|
119
|
-
|
120
|
-
FakeOxMods.properties[:person][:xpath].should == '//oxns:name[@type="personal"]'
|
121
|
-
FakeOxMods.properties[:person][:xpath_relative].should == 'oxns:name[@type="personal"]'
|
122
|
-
end
|
123
|
-
|
124
|
-
it "constructs templates for value-driven searches" do
|
125
|
-
FakeOxMods.properties[:name_][:xpath_constrained].should == '//oxns:name[contains(oxns:namePart, "#{constraint_value}")]'.gsub('"', '\"')
|
126
|
-
FakeOxMods.properties[:person][:xpath_constrained].should == '//oxns:name[@type="personal" and contains(oxns:namePart, "#{constraint_value}")]'.gsub('"', '\"')
|
127
|
-
|
128
|
-
# Example of how you could use these templates:
|
129
|
-
constraint_value = "SAMPLE CONSTRAINT VALUE"
|
130
|
-
constrained_query = eval( '"' + FakeOxMods.properties[:person][:xpath_constrained] + '"' )
|
131
|
-
constrained_query.should == '//oxns:name[@type="personal" and contains(oxns:namePart, "SAMPLE CONSTRAINT VALUE")]'
|
132
|
-
end
|
133
|
-
|
134
|
-
it "constructs xpath queries & templates for convenience methods" do
|
135
|
-
FakeOxMods.properties[:name_][:convenience_methods][:date][:xpath].should == '//oxns:name/oxns:namePart[@type="date"]'
|
136
|
-
FakeOxMods.properties[:name_][:convenience_methods][:date][:xpath_relative].should == 'oxns:namePart[@type="date"]'
|
137
|
-
FakeOxMods.properties[:name_][:convenience_methods][:date][:xpath_constrained].should == '//oxns:name[contains(oxns:namePart[@type="date"], "#{constraint_value}")]'.gsub('"', '\"')
|
138
|
-
|
139
|
-
FakeOxMods.properties[:person][:convenience_methods][:date][:xpath].should == '//oxns:name[@type="personal"]/oxns:namePart[@type="date"]'
|
140
|
-
FakeOxMods.properties[:person][:convenience_methods][:date][:xpath_relative].should == 'oxns:namePart[@type="date"]'
|
141
|
-
FakeOxMods.properties[:person][:convenience_methods][:date][:xpath_constrained].should == '//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "#{constraint_value}")]'.gsub('"', '\"')
|
142
|
-
|
143
|
-
end
|
144
|
-
|
145
|
-
it "constructs xpath queries & templates for subelements too" do
|
146
|
-
FakeOxMods.properties[:person][:convenience_methods][:displayForm][:xpath].should == '//oxns:name[@type="personal"]/oxns:displayForm'
|
147
|
-
FakeOxMods.properties[:person][:convenience_methods][:displayForm][:xpath_relative].should == 'oxns:displayForm'
|
148
|
-
FakeOxMods.properties[:person][:convenience_methods][:displayForm][:xpath_constrained].should == '//oxns:name[@type="personal" and contains(oxns:displayForm, "#{constraint_value}")]'.gsub('"', '\"')
|
149
|
-
end
|
150
|
-
|
151
|
-
it "supports subelements that are specified as separate properties" do
|
152
|
-
FakeOxMods.properties[:name_][:convenience_methods][:role][:xpath].should == '//oxns:name/oxns:role'
|
153
|
-
FakeOxMods.properties[:name_][:convenience_methods][:role][:xpath_relative].should == 'oxns:role'
|
154
|
-
FakeOxMods.properties[:name_][:convenience_methods][:role][:xpath_constrained].should == '//oxns:name[contains(oxns:role/oxns:roleTerm, "#{constraint_value}")]'.gsub('"', '\"')
|
155
|
-
end
|
156
|
-
|
157
|
-
it "supports treating attributes as properties" do
|
158
|
-
FakeOxMods.properties[:title_info][:convenience_methods][:language][:xpath].should == '//oxns:titleInfo/@lang'
|
159
|
-
FakeOxMods.properties[:title_info][:convenience_methods][:language][:xpath_relative].should == '@lang'
|
160
|
-
FakeOxMods.properties[:title_info][:convenience_methods][:language][:xpath_constrained].should == '//oxns:titleInfo[contains(@lang, "#{constraint_value}")]'.gsub('"', '\"')
|
161
|
-
end
|
162
|
-
|
163
|
-
it "should support deep nesting of properties" do
|
164
|
-
pending "requires property method to be recursive"
|
165
|
-
|
166
|
-
FakeOxMods.properties[:journal][:convenience_methods][:issue][:convenience_methods][:volume].should == {:xpath_constrained=>"//oxns:part[contains(oxns:detail[@type=\\\"volume\\\"], \\\"\#{constraint_value}\\\")]", :path=>"detail", :attributes=>{:type=>"volume"}, :xpath=>"//oxns:part/oxns:detail[@type=\"volume\"]", :xpath_relative=>"oxns:detail[@type=\"volume\"]"}
|
167
|
-
prop_info = FakeOxMods.property_info_for([:journal, :issue, :volume])
|
168
|
-
prop_info[:xpath_constrained].should == "//oxns:part[contains(oxns:detail[@type=\\\"volume\\\"], \\\"\#{constraint_value}\\\")]"
|
169
|
-
prop_info[:xpath].should == "//oxns:part/oxns:detail[@type=\"volume\"]"
|
170
|
-
prop_info[:xpath_relative].should == "oxns:detail[@type=\"volume\"]"
|
171
|
-
end
|
172
|
-
|
173
|
-
it "should support even deeper nesting of properties" do
|
174
|
-
pending "requires property method to be recursive"
|
175
|
-
|
176
|
-
FakeOxMods.properties[:journal][:convenience_methods][:issue][:convenience_methods][:start_page].should == {:xpath_constrained=>"//oxns:part[contains(oxns:detail[@type=\\\"volume\\\"], \\\"\#{constraint_value}\\\")]", :path=>"detail", :attributes=>{:type=>"volume"}, :xpath=>"//oxns:part/oxns:detail[@type=\"volume\"]", :xpath_relative=>"oxns:detail[@type=\"volume\"]"}
|
177
|
-
FakeOxMods.property_info_for([:journal, :issue, :end_page]).should == ""
|
178
|
-
end
|
179
|
-
|
180
|
-
it "should not overwrite default property info when adding a variant property" do
|
181
|
-
FakeOxMods.properties[:name_].should_not equal(FakeOxMods.properties[:person])
|
182
|
-
FakeOxMods.properties[:name_][:convenience_methods].should_not equal(FakeOxMods.properties[:person][:convenience_methods])
|
183
|
-
|
184
|
-
FakeOxMods.properties[:name_][:xpath].should_not == FakeOxMods.properties[:person][:xpath]
|
185
|
-
FakeOxMods.properties[:name_][:convenience_methods][:date][:xpath_constrained].should_not == FakeOxMods.properties[:person][:convenience_methods][:date][:xpath_constrained]
|
186
|
-
end
|
187
|
-
|
188
|
-
end
|
189
|
-
|
190
|
-
describe ".lookup" do
|
191
|
-
|
192
|
-
it "uses the generated xpath queries" do
|
193
|
-
@fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal"]', @fixturemods.ox_namespaces)
|
194
|
-
@fixturemods.lookup(:person)
|
195
|
-
|
196
|
-
@fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:namePart, "Beethoven, Ludwig van")]', @fixturemods.ox_namespaces)
|
197
|
-
@fixturemods.lookup(:person, "Beethoven, Ludwig van")
|
198
|
-
|
199
|
-
@fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "2010")]', @fixturemods.ox_namespaces)
|
200
|
-
@fixturemods.lookup(:person, :date=>"2010")
|
201
|
-
|
202
|
-
@fixturemods.ng_xml.expects(:xpath).with('//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "donor")]', @fixturemods.ox_namespaces)
|
203
|
-
@fixturemods.lookup(:person, :role=>"donor")
|
204
|
-
|
205
|
-
#
|
206
|
-
# This is the way we want to move towards... (currently implementing part of this in accessor_constrained_xpath)
|
207
|
-
# @fixturemods.ng_xml.expects(:xpath).with('//oxns:relatedItem/oxns:identifier[@type=\'issn\'] and contains("123-ABC-44567")]', @fixturemods.ox_namespaces)
|
208
|
-
# @fixturemods.lookup([:journal, :issn], "123-ABC-44567")
|
209
|
-
|
210
|
-
end
|
211
|
-
|
212
|
-
end
|
213
|
-
|
214
|
-
describe ".xpath_query_for" do
|
215
|
-
|
216
|
-
it "retrieves the generated xpath query to match your desires" do
|
217
|
-
@fixturemods.xpath_query_for(:person).should == '//oxns:name[@type="personal"]'
|
218
|
-
|
219
|
-
@fixturemods.xpath_query_for(:person, "Beethoven, Ludwig van").should == '//oxns:name[@type="personal" and contains(oxns:namePart, "Beethoven, Ludwig van")]'
|
220
|
-
|
221
|
-
@fixturemods.xpath_query_for(:person, :date=>"2010").should == '//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "2010")]'
|
222
|
-
|
223
|
-
@fixturemods.xpath_query_for(:person, :role=>"donor").should == '//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "donor")]'
|
224
|
-
|
225
|
-
@fixturemods.xpath_query_for([:person,:date]).should == '//oxns:name[@type="personal"]/oxns:namePart[@type="date"]'
|
226
|
-
|
227
|
-
@fixturemods.xpath_query_for([:person,:date], "2010").should == '//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "2010")]'
|
228
|
-
end
|
229
|
-
|
230
|
-
it "parrots any strings back to you (in case you already have an xpath query)" do
|
231
|
-
@fixturemods.xpath_query_for('//oxns:name[@type="personal"]/oxns:namePart[@type="date"]').should == '//oxns:name[@type="personal"]/oxns:namePart[@type="date"]'
|
232
|
-
end
|
233
|
-
|
234
|
-
end
|
235
|
-
|
236
|
-
describe "#generate_xpath" do
|
237
|
-
it "should generate an xpath query from the options in the provided hash and should support generating xpaths with constraint values" do
|
238
|
-
opts1 = {:path=>"name", :default_content_path=>"namePart"}
|
239
|
-
opts2 = {:path=>"originInfo"}
|
240
|
-
opts3 = {:path=>["name", "namePart"]}
|
241
|
-
FakeOxMods.generate_xpath( opts1 ).should == '//oxns:name'
|
242
|
-
FakeOxMods.generate_xpath( opts1, :constraints=>:default ).should == '//oxns:name[contains(oxns:namePart, "#{constraint_value}")]'
|
243
|
-
FakeOxMods.generate_xpath( opts2, :constraints=>:default ).should == '//oxns:originInfo[contains("#{constraint_value}")]'
|
244
|
-
|
245
|
-
FakeOxMods.generate_xpath( opts1, :variations=>{:attributes=>{:type=>"personal"}} ).should == '//oxns:name[@type="personal"]'
|
246
|
-
FakeOxMods.generate_xpath( opts1, :variations=>{:attributes=>{:type=>"personal"}}, :constraints=>:default ).should == '//oxns:name[@type="personal" and contains(oxns:namePart, "#{constraint_value}")]'
|
247
|
-
|
248
|
-
FakeOxMods.generate_xpath( opts1, :constraints=>{:path=>"namePart", :attributes=>{:type=>"date"}} ).should == '//oxns:name[contains(oxns:namePart[@type="date"], "#{constraint_value}")]'
|
249
|
-
FakeOxMods.generate_xpath( opts1, :constraints=>{:path=>"namePart", :attributes=>{:type=>"date"}}, :variations=>{:attributes=>{:type=>"personal"}} ).should == '//oxns:name[@type="personal" and contains(oxns:namePart[@type="date"], "#{constraint_value}")]'
|
250
|
-
FakeOxMods.generate_xpath(FakeOxMods.properties[:person], :variations=>{:attributes=>{:type=>"personal"}}, :constraints=>{:path=>"role", :default_content_path=>"roleTerm"}, :subelement_of=>":person").should == '//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "#{constraint_value}")]'
|
251
|
-
|
252
|
-
FakeOxMods.generate_xpath(opts1, :variations=>{:attributes=>{:type=>"personal"}, :subelement_path=>"displayForm" } ).should == '//oxns:name[@type="personal"]/oxns:displayForm'
|
253
|
-
FakeOxMods.generate_xpath(opts1, :variations=>{:attributes=>{:type=>"personal"}}, :constraints=>{:path=>"displayForm"} ).should == '//oxns:name[@type="personal" and contains(oxns:displayForm, "#{constraint_value}")]'
|
254
|
-
FakeOxMods.generate_xpath(opts1, :variations=>{:attributes=>{:type=>"personal"}, :subelement_path=>["role", "roleTerm"] } ).should == '//oxns:name[@type="personal"]/oxns:role/oxns:roleTerm'
|
255
|
-
|
256
|
-
FakeOxMods.generate_xpath( opts3, :variations=>{:attributes=>{:type=>"date"}} ).should == '//oxns:name/oxns:namePart[@type="date"]'
|
257
|
-
FakeOxMods.generate_xpath( opts3, :variations=>{:attributes=>{:type=>"date"}}, :constraints=>:default ).should == '//oxns:name/oxns:namePart[@type="date" and contains("#{constraint_value}")]'
|
258
|
-
|
259
|
-
FakeOxMods.generate_xpath( {:path=>["relatedItem", "identifier"]}, :variations=>{:attributes=>{:type=>"issn"}}, :constraints=>:default ).should == '//oxns:relatedItem/oxns:identifier[@type="issn" and contains("#{constraint_value}")]'
|
260
|
-
|
261
|
-
end
|
262
|
-
|
263
|
-
|
264
|
-
it "should support relative paths" do
|
265
|
-
relative_opts = {:path=>"namePart"}
|
266
|
-
FakeOxMods.generate_xpath( relative_opts, :variations=>{:attributes=>{:type=>"date"}}, :relative=>true).should == 'oxns:namePart[@type="date"]'
|
267
|
-
end
|
268
|
-
|
269
|
-
it "should work with real properties hashes" do
|
270
|
-
FakeOxMods.generate_xpath(FakeOxMods.properties[:person], :variations=>FakeOxMods.properties[:person]).should == "//oxns:name[@type=\"personal\"]"
|
271
|
-
FakeOxMods.generate_xpath(FakeOxMods.properties[:person], :variations=>FakeOxMods.properties[:person], :constraints=>{:path=>"role", :default_content_path=>"roleTerm"}, :subelement_of=>":person").should == '//oxns:name[@type="personal" and contains(oxns:role/oxns:roleTerm, "#{constraint_value}")]'
|
272
|
-
date_hash = FakeOxMods.properties[:person][:convenience_methods][:date]
|
273
|
-
FakeOxMods.generate_xpath( date_hash, :variations=>date_hash, :relative=>true ).should == 'oxns:namePart[@type="date"]'
|
274
|
-
end
|
275
|
-
|
276
|
-
it "should support custom templates" do
|
277
|
-
opts = {:path=>"name", :default_content_path=>"namePart"}
|
278
|
-
FakeOxMods.generate_xpath( opts, :template=>'/#{prefix}:sampleNode/#{prefix}:#{path}[contains(#{default_content_path}, \":::constraint_value:::\")]' ).should == '/oxns:sampleNode/oxns:name[contains(namePart, "#{constraint_value}")]'
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
describe "#builder_template" do
|
283
|
-
|
284
|
-
it "should generate a template call for passing into the builder block (assumes 'xml' as the argument for the block)" do
|
285
|
-
FakeOxMods.builder_template([:person,:date]).should == 'xml.namePart( \'#{builder_new_value}\', :type=>\'date\' )'
|
286
|
-
FakeOxMods.builder_template([:name_,:affiliation]).should == 'xml.affiliation( \'#{builder_new_value}\' )'
|
287
|
-
|
288
|
-
simple_role_builder_template = 'xml.role( :type=>\'text\' ) { xml.roleTerm( \'#{builder_new_value}\' ) }'
|
289
|
-
FakeOxMods.builder_template([:role]).should == simple_role_builder_template
|
290
|
-
FakeOxMods.builder_template([:person,:role]).should == simple_role_builder_template
|
291
|
-
|
292
|
-
marcrelator_role_builder_template = 'xml.role( :type=>\'code\', :authority=>\'marcrelator\' ) { xml.roleTerm( \'#{builder_new_value}\' ) }'
|
293
|
-
FakeOxMods.builder_template([:role], {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}} ).should == marcrelator_role_builder_template
|
294
|
-
FakeOxMods.builder_template([:person,:role], {:attributes=>{"type"=>"code", "authority"=>"marcrelator"}} ).should == marcrelator_role_builder_template
|
295
|
-
end
|
296
|
-
|
297
|
-
it "should work with deeply nested properties" do
|
298
|
-
FakeOxMods.builder_template([:issue, :volume]).should == "xml.detail( '\#{builder_new_value}', :type=>'volume' )"
|
299
|
-
FakeOxMods.builder_template([:volume, :number]).should == "xml.number( '\#{builder_new_value}' )"
|
300
|
-
FakeOxMods.builder_template([:journal, :issue, :level]).should == "xml.detail( :type=>'number' ) { xml.number( '\#{builder_new_value}' ) }"
|
301
|
-
FakeOxMods.builder_template([:journal, :issue, :volume]).should == "xml.detail( '\#{builder_new_value}', :type=>'volume' )"
|
302
|
-
FakeOxMods.builder_template([:journal, :issue, :volume, :number]).should == "xml.number( '\#{builder_new_value}' )"
|
303
|
-
FakeOxMods.builder_template([:journal, :issue, :start_page]).should == "xml.extent( :unit=>'pages' ) { xml.start( '\#{builder_new_value}' ) }"
|
304
|
-
end
|
305
|
-
|
306
|
-
end
|
307
|
-
|
308
|
-
describe "#applicable_attributes" do
|
309
|
-
it "returns a Hash where all of the values are strings" do
|
310
|
-
FakeOxMods.send(:applicable_attributes, {:type=>"date"} ).should == {:type=>"date"}
|
311
|
-
FakeOxMods.send(:applicable_attributes, ["authority", {:type=>["text","code"]}] ).should == {:type=>"text"}
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
end
|