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
data/History.textile
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
1.1.0
|
2
|
+
|
3
|
+
HYDRA-371: Provide a way to specify a term that points to nodes where an attribute is not set
|
4
|
+
|
5
|
+
Add support for this syntax in Terminologies, where an attribute value can be :none. When an attribute's value is set to :none, a not() predicate is used in the resulting xpath
|
6
|
+
|
7
|
+
t.computing_id(:path=>"namePart", :attributes=>{:type=>:none})
|
8
|
+
|
9
|
+
will result in an xpath that looks like:
|
10
|
+
|
11
|
+
//namePart[not(@type)]
|
12
|
+
|
13
|
+
namePart[not(@type)]
|
14
|
+
|
1
15
|
1.0.1
|
2
16
|
|
3
17
|
HYDRA-329: Allow for NamedTermProxies at root of Terminology
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0
|
1
|
+
1.1.0
|
@@ -10,7 +10,10 @@ class OM::Samples::ModsArticle
|
|
10
10
|
t.language(:path=>{:attribute=>"lang"})
|
11
11
|
}
|
12
12
|
t.abstract
|
13
|
-
t.
|
13
|
+
t.subject{
|
14
|
+
t.topic
|
15
|
+
}
|
16
|
+
t.topic_tag(:ref=>[:subject, :topic])
|
14
17
|
# This is a mods:name. The underscore is purely to avoid namespace conflicts.
|
15
18
|
t.name_ {
|
16
19
|
# this is a namepart
|
@@ -24,6 +27,7 @@ class OM::Samples::ModsArticle
|
|
24
27
|
t.last_name(:path=>"namePart", :attributes=>{:type=>"family"})
|
25
28
|
t.first_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
|
26
29
|
t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
|
30
|
+
t.name_content(:path=>"text()")
|
27
31
|
}
|
28
32
|
# lookup :person, :first_name
|
29
33
|
t.person(:ref=>:name, :attributes=>{:type=>"personal"})
|
@@ -61,4 +65,4 @@ class OM::Samples::ModsArticle
|
|
61
65
|
# renamed family_name => last_name
|
62
66
|
# start_page & end_page now accessible as [:journal, :issue, :pages, :start] (etc.)
|
63
67
|
|
64
|
-
end
|
68
|
+
end
|
data/lib/om/xml.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
require "om/xml/container"
|
2
|
-
require "om/xml/accessors"
|
3
2
|
require "om/xml/validation"
|
4
|
-
require "om/xml/properties"
|
5
|
-
require "om/xml/property_value_operators"
|
6
|
-
require "om/xml/generator"
|
7
3
|
|
8
4
|
require "om/xml/terminology"
|
9
5
|
require "om/xml/term"
|
@@ -49,13 +45,8 @@ module OM::XML
|
|
49
45
|
|
50
46
|
def self.included(klass)
|
51
47
|
klass.extend(ClassMethods)
|
52
|
-
|
53
48
|
klass.send(:include, OM::XML::Container)
|
54
|
-
klass.send(:include, OM::XML::Accessors)
|
55
49
|
klass.send(:include, OM::XML::Validation)
|
56
|
-
klass.send(:include, OM::XML::Properties)
|
57
|
-
klass.send(:include, OM::XML::PropertyValueOperators)
|
58
|
-
klass.send(:include, OM::XML::Generator)
|
59
50
|
end
|
60
51
|
|
61
52
|
|
@@ -1,6 +1,13 @@
|
|
1
1
|
module OM::XML::NodeGenerator
|
2
2
|
|
3
3
|
# Module Methods -- These methods can be called directly on the Module itself
|
4
|
+
# @param OM::XML::Term term The term to generate a node based on
|
5
|
+
# @param String builder_new_value The new value to insert into the generated node
|
6
|
+
# @returns Nokogiri::XML::Document
|
7
|
+
#
|
8
|
+
# Ex.
|
9
|
+
# term = t.retrieve_term(:person, :first_name)
|
10
|
+
# OM::XML::NodeGenerator.generate(term, "John")
|
4
11
|
def self.generate(term, builder_new_value, opts={})
|
5
12
|
template = term.xml_builder_template(opts)
|
6
13
|
builder_call_body = eval('"' + template + '"')
|
data/lib/om/xml/term.rb
CHANGED
@@ -129,6 +129,9 @@ class OM::XML::Term
|
|
129
129
|
|
130
130
|
include OM::TreeNode
|
131
131
|
|
132
|
+
# h2. Namespaces
|
133
|
+
# By default, OM assumes that all terms in a Terminology have the namespace set in the root of the document. If you want to set a different namespace for a Term, pass :namespasce_prefix into its initializer (or call .namespace_prefix= on its builder)
|
134
|
+
# If a node has _no_ namespace, you must explicitly set namespace_prefix to nil.
|
132
135
|
def initialize(name, opts={})
|
133
136
|
opts = {:namespace_prefix=>"oxns", :ancestors=>[], :children=>{}}.merge(opts)
|
134
137
|
[:children, :ancestors,:path, :index_as, :required, :type, :variant_of, :path, :attributes, :default_content_path, :namespace_prefix].each do |accessor_name|
|
@@ -7,7 +7,10 @@ module OM::XML::TermValueOperators
|
|
7
7
|
# Retrieves all of the nodes from the current document that match +term_pointer+ and returns an array of their values
|
8
8
|
def term_values(*term_pointer)
|
9
9
|
result = []
|
10
|
-
|
10
|
+
xpath = self.class.terminology.xpath_with_indexes(*term_pointer)
|
11
|
+
#if value is on line by itself sometimes does not trim leading and trailing whitespace for a text node so will detect and fix it
|
12
|
+
trim_text = !xpath.nil? && !xpath.index("text()").nil?
|
13
|
+
find_by_terms(*term_pointer).each {|node| result << (trim_text ? node.text.strip : node.text) }
|
11
14
|
# find_by_terms(*OM.destringify(term_pointer)).each {|node| result << node.text }
|
12
15
|
return result
|
13
16
|
end
|
@@ -128,6 +131,9 @@ module OM::XML::TermValueOperators
|
|
128
131
|
template_args = OM.pointers_to_flat_array(template_args,false)
|
129
132
|
template = self.class.terminology.xml_builder_template( *template_args )
|
130
133
|
end
|
134
|
+
|
135
|
+
#if there is an xpath element pointing to text() need to change to just 'text' so it references the text method for the parent node
|
136
|
+
template.gsub!(/text\(\)/, 'text')
|
131
137
|
|
132
138
|
builder = Nokogiri::XML::Builder.with(parent_node) do |xml|
|
133
139
|
new_values.each do |builder_new_value|
|
@@ -240,4 +246,4 @@ module OM::XML::TermValueOperators
|
|
240
246
|
|
241
247
|
private :node_from_set
|
242
248
|
|
243
|
-
end
|
249
|
+
end
|
@@ -1,32 +1,50 @@
|
|
1
1
|
module OM::XML::TermXpathGenerator
|
2
2
|
|
3
|
-
|
3
|
+
# Generate relative xpath for a term
|
4
|
+
# @param [OM::XML::Term] term that you want to generate relative xpath for
|
5
|
+
#
|
6
|
+
# In most cases, the resulting xpath will be the Term's path with the appropriate namespace appended to it.
|
7
|
+
# If the Term specifies any attributes,
|
8
|
+
# Special Case: attribute Terms
|
9
|
+
# If the Term's path is set to {:attribute=>attr_name}, the resulting xpath will points to a node attribute named attr_name
|
10
|
+
# ie. a path fo {:attribute=>"lang"} will result in a relative xpath of "@lang"
|
11
|
+
# Special Case: xpath functions
|
12
|
+
# If the Term's path variable is text(), it will be treated as an xpath function (no namespace) and turned into "text()[normalize-space(.)]"
|
13
|
+
def self.generate_relative_xpath(term)
|
4
14
|
template = ""
|
5
15
|
predicates = []
|
6
16
|
|
7
|
-
if
|
17
|
+
if term.namespace_prefix.nil?
|
8
18
|
complete_prefix = ""
|
9
19
|
else
|
10
|
-
complete_prefix =
|
20
|
+
complete_prefix = term.namespace_prefix + ":"
|
11
21
|
end
|
12
22
|
|
13
|
-
if
|
14
|
-
if
|
15
|
-
base_path = "@"+
|
23
|
+
if term.path.kind_of?(Hash)
|
24
|
+
if term.path.has_key?(:attribute)
|
25
|
+
base_path = "@"+term.path[:attribute]
|
16
26
|
else
|
17
|
-
raise "#{
|
27
|
+
raise "#{term.path} is an invalid path for an OM::XML::Term. You should provide either a string or {:attributes=>XXX}"
|
18
28
|
end
|
19
29
|
else
|
20
|
-
|
21
|
-
|
30
|
+
if term.path == "text()"
|
31
|
+
base_path = "#{term.path}[normalize-space(.)]"
|
32
|
+
else
|
33
|
+
unless term.namespace_prefix.nil?
|
34
|
+
template << complete_prefix
|
35
|
+
end
|
36
|
+
base_path = term.path
|
22
37
|
end
|
23
|
-
base_path = mapper.path
|
24
38
|
end
|
25
39
|
template << base_path
|
26
40
|
|
27
|
-
unless
|
28
|
-
|
29
|
-
|
41
|
+
unless term.attributes.nil?
|
42
|
+
term.attributes.each_pair do |attr_name, attr_value|
|
43
|
+
if attr_value == :none
|
44
|
+
predicates << "not(@#{attr_name})"
|
45
|
+
else
|
46
|
+
predicates << "@#{attr_name}=\"#{attr_value}\""
|
47
|
+
end
|
30
48
|
end
|
31
49
|
end
|
32
50
|
|
@@ -37,29 +55,33 @@ module OM::XML::TermXpathGenerator
|
|
37
55
|
return template
|
38
56
|
end
|
39
57
|
|
40
|
-
|
41
|
-
|
42
|
-
|
58
|
+
# Generate absolute xpath for a Term
|
59
|
+
# @param [OM::XML::Term] term that you want to generate absolute xpath for
|
60
|
+
#
|
61
|
+
# Absolute xpaths always begin with "//". They are generated by relying on the Term's relative xpath and the absolute xpath of its parent node.
|
62
|
+
def self.generate_absolute_xpath(term)
|
63
|
+
relative = generate_relative_xpath(term)
|
64
|
+
if term.parent.nil?
|
43
65
|
return "//#{relative}"
|
44
66
|
else
|
45
|
-
return
|
67
|
+
return term.parent.xpath_absolute + "/" + relative
|
46
68
|
end
|
47
69
|
end
|
48
70
|
|
49
|
-
def self.generate_constrained_xpath(
|
50
|
-
if
|
71
|
+
def self.generate_constrained_xpath(term)
|
72
|
+
if term.namespace_prefix.nil?
|
51
73
|
complete_prefix = ""
|
52
74
|
else
|
53
|
-
complete_prefix =
|
75
|
+
complete_prefix = term.namespace_prefix + ":"
|
54
76
|
end
|
55
77
|
|
56
|
-
absolute = generate_absolute_xpath(
|
78
|
+
absolute = generate_absolute_xpath(term)
|
57
79
|
constraint_predicates = []
|
58
80
|
|
59
81
|
arguments_for_contains_function = []
|
60
82
|
|
61
|
-
if !
|
62
|
-
arguments_for_contains_function << "#{complete_prefix}#{
|
83
|
+
if !term.default_content_path.nil?
|
84
|
+
arguments_for_contains_function << "#{complete_prefix}#{term.default_content_path}"
|
63
85
|
end
|
64
86
|
|
65
87
|
# If no subelements have been specified to search within, set contains function to search within the current node
|
@@ -75,20 +97,25 @@ module OM::XML::TermXpathGenerator
|
|
75
97
|
return template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }.gsub('"', '\"')
|
76
98
|
end
|
77
99
|
|
78
|
-
|
100
|
+
# Generate an xpath of the chosen +type+ for the given Term.
|
101
|
+
# @param [OM::XML::Term] term that you want to generate relative xpath for
|
102
|
+
# @param [Symbol] the type of xpath to generate, :relative, :abolute, or :constrained
|
103
|
+
def self.generate_xpath(term, type)
|
79
104
|
case type
|
80
105
|
when :relative
|
81
|
-
self.generate_relative_xpath(
|
106
|
+
self.generate_relative_xpath(term)
|
82
107
|
when :absolute
|
83
|
-
self.generate_absolute_xpath(
|
108
|
+
self.generate_absolute_xpath(term)
|
84
109
|
when :constrained
|
85
|
-
self.generate_constrained_xpath(
|
110
|
+
self.generate_constrained_xpath(term)
|
86
111
|
end
|
87
112
|
end
|
88
113
|
|
89
114
|
# Use the given +terminology+ to generate an xpath with (optional) node indexes for each of the term pointers.
|
90
115
|
# Ex. OM::XML::TermXpathGenerator.xpath_with_indexes(my_terminology, {:conference=>0}, {:role=>1}, :text )
|
91
116
|
# will yield an xpath similar to this: '//oxns:name[@type="conference"][1]/oxns:role[2]/oxns:roleTerm[@type="text"]'
|
117
|
+
# @param [OM::XML::Terminology] terminology to generate xpath based on
|
118
|
+
# @param [String -- OM term pointer] pointers identifying the node to generate xpath for
|
92
119
|
def self.generate_xpath_with_indexes(terminology, *pointers)
|
93
120
|
if pointers.first.nil?
|
94
121
|
root_term = terminology.root_terms.first
|
@@ -183,7 +210,9 @@ module OM::XML::TermXpathGenerator
|
|
183
210
|
return xpath
|
184
211
|
end
|
185
212
|
|
186
|
-
|
213
|
+
# Turns an Array into a String containing values separated by a delimiter. Defaults to comma as a delimiter.
|
214
|
+
# @param [Array] values_array to convert
|
215
|
+
# @param [String] delimiter. Default: ", "
|
187
216
|
def self.delimited_list( values_array, delimiter=", ")
|
188
217
|
result = values_array.collect{|a| a + delimiter}.to_s.chomp(delimiter)
|
189
218
|
end
|
@@ -224,4 +253,4 @@ module OM::XML::TermXpathGenerator
|
|
224
253
|
return modified_query
|
225
254
|
end
|
226
255
|
|
227
|
-
end
|
256
|
+
end
|
data/om.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{om}
|
8
|
-
s.version = "1.0
|
8
|
+
s.version = "1.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Matt Zumwalt"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-03-05}
|
13
13
|
s.description = %q{OM (Opinionated Metadata): A library to help you tame sprawling XML schemas like MODS. Wraps Nokogiri documents in objects with miscellaneous helper methods for doing things like retrieve generated xpath queries or look up properties based on a simplified DSL}
|
14
14
|
s.email = %q{matt.zumwalt@yourmediashelf.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -33,14 +33,10 @@ Gem::Specification.new do |s|
|
|
33
33
|
"lib/om/samples/mods_article.rb",
|
34
34
|
"lib/om/tree_node.rb",
|
35
35
|
"lib/om/xml.rb",
|
36
|
-
"lib/om/xml/accessors.rb",
|
37
36
|
"lib/om/xml/container.rb",
|
38
37
|
"lib/om/xml/document.rb",
|
39
|
-
"lib/om/xml/generator.rb",
|
40
38
|
"lib/om/xml/named_term_proxy.rb",
|
41
39
|
"lib/om/xml/node_generator.rb",
|
42
|
-
"lib/om/xml/properties.rb",
|
43
|
-
"lib/om/xml/property_value_operators.rb",
|
44
40
|
"lib/om/xml/term.rb",
|
45
41
|
"lib/om/xml/term_value_operators.rb",
|
46
42
|
"lib/om/xml/term_xpath_generator.rb",
|
@@ -56,15 +52,11 @@ Gem::Specification.new do |s|
|
|
56
52
|
"spec/integration/rights_metadata_integration_example_spec.rb",
|
57
53
|
"spec/spec.opts",
|
58
54
|
"spec/spec_helper.rb",
|
59
|
-
"spec/unit/accessors_spec.rb",
|
60
55
|
"spec/unit/container_spec.rb",
|
61
56
|
"spec/unit/document_spec.rb",
|
62
|
-
"spec/unit/generator_spec.rb",
|
63
57
|
"spec/unit/named_term_proxy_spec.rb",
|
64
58
|
"spec/unit/node_generator_spec.rb",
|
65
59
|
"spec/unit/om_spec.rb",
|
66
|
-
"spec/unit/properties_spec.rb",
|
67
|
-
"spec/unit/property_value_operators_spec.rb",
|
68
60
|
"spec/unit/term_builder_spec.rb",
|
69
61
|
"spec/unit/term_spec.rb",
|
70
62
|
"spec/unit/term_value_operators_spec.rb",
|
@@ -81,15 +73,11 @@ Gem::Specification.new do |s|
|
|
81
73
|
s.test_files = [
|
82
74
|
"spec/integration/rights_metadata_integration_example_spec.rb",
|
83
75
|
"spec/spec_helper.rb",
|
84
|
-
"spec/unit/accessors_spec.rb",
|
85
76
|
"spec/unit/container_spec.rb",
|
86
77
|
"spec/unit/document_spec.rb",
|
87
|
-
"spec/unit/generator_spec.rb",
|
88
78
|
"spec/unit/named_term_proxy_spec.rb",
|
89
79
|
"spec/unit/node_generator_spec.rb",
|
90
80
|
"spec/unit/om_spec.rb",
|
91
|
-
"spec/unit/properties_spec.rb",
|
92
|
-
"spec/unit/property_value_operators_spec.rb",
|
93
81
|
"spec/unit/term_builder_spec.rb",
|
94
82
|
"spec/unit/term_spec.rb",
|
95
83
|
"spec/unit/term_value_operators_spec.rb",
|
@@ -11,9 +11,11 @@
|
|
11
11
|
</titleInfo>
|
12
12
|
|
13
13
|
<name type="personal">
|
14
|
+
Describes a person
|
14
15
|
<namePart type="family">FAMILY NAME</namePart>
|
15
16
|
<namePart type="given">GIVEN NAMES</namePart>
|
16
17
|
<namePart type="termsOfAddress">DR.</namePart>
|
18
|
+
<namePart>PERSON_ID</namePart>
|
17
19
|
<displayForm>NAME AS IT APPEARS</displayForm>
|
18
20
|
<affiliation>FACULTY, UNIVERSITY</affiliation>
|
19
21
|
<role>
|
@@ -28,6 +30,7 @@
|
|
28
30
|
<namePart type="family">Gautama</namePart>
|
29
31
|
<namePart type="given">Siddartha</namePart>
|
30
32
|
<namePart type="termsOfAddress">Prince</namePart>
|
33
|
+
<namePart>123987</namePart>
|
31
34
|
<affiliation>Nirvana</affiliation>
|
32
35
|
<role>
|
33
36
|
<roleTerm authority="marcrelator" type="text">teacher</roleTerm>
|
data/spec/unit/document_spec.rb
CHANGED
@@ -35,6 +35,7 @@ describe "OM::XML::Document" do
|
|
35
35
|
t.last_name(:path=>"namePart", :attributes=>{:type=>"family"})
|
36
36
|
t.first_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
|
37
37
|
t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
|
38
|
+
t.person_id(:path=>"namePart", :attributes=>{:type=>:none})
|
38
39
|
}
|
39
40
|
# lookup :person, :first_name
|
40
41
|
t.person(:ref=>:name, :attributes=>{:type=>"personal"})
|
@@ -113,6 +114,9 @@ describe "OM::XML::Document" do
|
|
113
114
|
@mods_article.find_by_terms( {:person=>1}, :first_name ).class.should == Nokogiri::XML::NodeSet
|
114
115
|
@mods_article.find_by_terms( {:person=>1}, :first_name ).first.text.should == "Siddartha"
|
115
116
|
end
|
117
|
+
it "should find a NodeSet where a terminology attribute has been set to :none" do
|
118
|
+
@mods_article.find_by_terms( {:person=>1}, :person_id).first.text.should == "123987"
|
119
|
+
end
|
116
120
|
it "should support accessors whose relative_xpath is a lookup array instead of an xpath string" do
|
117
121
|
# pending "this only impacts scenarios where we want to display & edit"
|
118
122
|
DocumentTest.terminology.retrieve_term(:title_info, :language).path.should == {:attribute=>"lang"}
|
@@ -128,7 +132,7 @@ describe "OM::XML::Document" do
|
|
128
132
|
pending "Can't decide if it's better to return nil or raise an error. Choosing informative errors for now."
|
129
133
|
@mods_article.find_by_terms( {:foo=>20}, :bar ).should == nil
|
130
134
|
end
|
131
|
-
|
135
|
+
|
132
136
|
it "should support terms that point to attributes instead of nodes" do
|
133
137
|
@mods_article.find_by_terms( {:title_info=>1}, :language ).first.text.should == "finnish"
|
134
138
|
end
|
@@ -16,6 +16,10 @@ describe "OM::XML::TermValueOperators" do
|
|
16
16
|
result.length.should == expected_values.length
|
17
17
|
expected_values.each {|v| result.should include(v)}
|
18
18
|
end
|
19
|
+
|
20
|
+
it "should ignore whitespace elements for a term pointing to a text() node for an element that contains children" do
|
21
|
+
@article.term_values(:name, :name_content).should == ["Describes a person"]
|
22
|
+
end
|
19
23
|
|
20
24
|
end
|
21
25
|
|
@@ -72,7 +76,7 @@ describe "OM::XML::TermValueOperators" do
|
|
72
76
|
end
|
73
77
|
|
74
78
|
it "should destringify the field key/find_by_terms_and_value pointer" do
|
75
|
-
OM::Samples::ModsArticle.terminology.expects(:xpath_with_indexes).with( *[{:person=>0}, :role]).times(
|
79
|
+
OM::Samples::ModsArticle.terminology.expects(:xpath_with_indexes).with( *[{:person=>0}, :role]).times(10).returns("//oxns:name[@type=\"personal\"][1]/oxns:role")
|
76
80
|
OM::Samples::ModsArticle.terminology.stubs(:xpath_with_indexes).with( *[{:person=>0}]).returns("//oxns:name[@type=\"personal\"][1]")
|
77
81
|
@article.update_values( { [{":person"=>"0"}, "role"]=>"the role" } )
|
78
82
|
@article.update_values( { [{"person"=>"0"}, "role"]=>"the role" } )
|
@@ -183,6 +187,13 @@ describe "OM::XML::TermValueOperators" do
|
|
183
187
|
@article.update_values({[:journal, :title_info]=>{"0"=>:delete}})
|
184
188
|
@article.term_values(:journal, :title_info).should == ['mork']
|
185
189
|
end
|
190
|
+
|
191
|
+
it "should retain other child nodes when updating a text content term and shoud not append an additional text node but update text in place" do
|
192
|
+
@article.term_values(:name,:name_content).should == ["Describes a person"]
|
193
|
+
@article.update_values({[:name, :name_content]=>"Test text"})
|
194
|
+
@article.term_values(:name,:name_content).should == ["Test text"]
|
195
|
+
@article.find_by_terms(:name).children.length().should == 30
|
196
|
+
end
|
186
197
|
|
187
198
|
end
|
188
199
|
|
@@ -406,4 +417,4 @@ describe "OM::XML::TermValueOperators" do
|
|
406
417
|
end
|
407
418
|
end
|
408
419
|
|
409
|
-
end
|
420
|
+
end
|
@@ -22,6 +22,8 @@ describe "OM::XML::TermXpathGeneratorSpec" do
|
|
22
22
|
@test_term_with_default_path = OM::XML::Term.new(:volume, :path=>"detail", :attributes=>{:type=>"volume"}, :default_content_path=>"number")
|
23
23
|
@test_role_text = OM::XML::Term.new(:role_text, :path=>"roleTerm", :attributes=>{:type=>"text"})
|
24
24
|
@test_lang_attribute = OM::XML::Term.new(:language, :path=>{:attribute=>"lang"})
|
25
|
+
@test_none_attribute_value = OM::XML::Term.new(:person_id, :path=>"namePart", :attributes=>{:type=>:none})
|
26
|
+
|
25
27
|
end
|
26
28
|
|
27
29
|
it "should support terms that are pointers to attribute values" do
|
@@ -51,6 +53,14 @@ describe "OM::XML::TermXpathGeneratorSpec" do
|
|
51
53
|
@test_term.namespace_prefix = nil
|
52
54
|
OM::XML::TermXpathGenerator.generate_relative_xpath(@test_term).should == 'namePart[@type="termsOfAddress"]'
|
53
55
|
end
|
56
|
+
it "should not use a namespace for a path set to text() and should include normalize-space to ignore white space" do
|
57
|
+
text_term = OM::XML::Term.new(:title_content, :path=>"text()")
|
58
|
+
OM::XML::TermXpathGenerator.generate_relative_xpath(text_term).should == 'text()[normalize-space(.)]'
|
59
|
+
end
|
60
|
+
it "should set a 'not' predicate if the attribute value is :none" do
|
61
|
+
OM::XML::TermXpathGenerator.generate_relative_xpath(@test_none_attribute_value).should == 'oxns:namePart[not(@type)]'
|
62
|
+
end
|
63
|
+
|
54
64
|
end
|
55
65
|
|
56
66
|
describe "generate_absolute_xpath" do
|
@@ -108,4 +118,4 @@ describe "OM::XML::TermXpathGeneratorSpec" do
|
|
108
118
|
OM::XML::TermXpathGenerator.generate_constrained_xpath(@test_term_with_default_path).should == '//oxns:detail[contains(oxns:number[@type="volume"], "#{constraint_value}")]'.gsub('"', '\"')
|
109
119
|
end
|
110
120
|
|
111
|
-
end
|
121
|
+
end
|