Skip to content

Commit 56695ef

Browse files
committed
Fix to allow for editing mixed text and child nodes HYDRA-355
1 parent 94a7f60 commit 56695ef

File tree

6 files changed

+39
-10
lines changed

6 files changed

+39
-10
lines changed

lib/om/samples/mods_article.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class OM::Samples::ModsArticle
2424
t.last_name(:path=>"namePart", :attributes=>{:type=>"family"})
2525
t.first_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
2626
t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
27+
t.name_content(:path=>"text()")
2728
}
2829
# lookup :person, :first_name
2930
t.person(:ref=>:name, :attributes=>{:type=>"personal"})
@@ -61,4 +62,4 @@ class OM::Samples::ModsArticle
6162
# renamed family_name => last_name
6263
# start_page & end_page now accessible as [:journal, :issue, :pages, :start] (etc.)
6364

64-
end
65+
end

lib/om/xml/term_value_operators.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ module OM::XML::TermValueOperators
77
# Retrieves all of the nodes from the current document that match +term_pointer+ and returns an array of their values
88
def term_values(*term_pointer)
99
result = []
10-
find_by_terms(*term_pointer).each {|node| result << node.text }
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) }
1114
# find_by_terms(*OM.destringify(term_pointer)).each {|node| result << node.text }
1215
return result
1316
end
@@ -128,6 +131,9 @@ def insert_from_template(parent_node, new_values, template)
128131
template_args = OM.pointers_to_flat_array(template_args,false)
129132
template = self.class.terminology.xml_builder_template( *template_args )
130133
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')
131137

132138
builder = Nokogiri::XML::Builder.with(parent_node) do |xml|
133139
new_values.each do |builder_new_value|
@@ -240,4 +246,4 @@ def node_from_set(nodeset, index)
240246

241247
private :node_from_set
242248

243-
end
249+
end

lib/om/xml/term_xpath_generator.rb

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,14 @@ def self.generate_relative_xpath(mapper)
1717
raise "#{mapper.path} is an invalid path for an OM::XML::Term. You should provide either a string or {:attributes=>XXX}"
1818
end
1919
else
20-
unless mapper.namespace_prefix.nil?
21-
template << complete_prefix
20+
if mapper.path == "text()"
21+
base_path = "#{mapper.path}[normalize-space(.)]"
22+
else
23+
unless mapper.namespace_prefix.nil?
24+
template << complete_prefix
25+
end
26+
base_path = mapper.path
2227
end
23-
base_path = mapper.path
2428
end
2529
template << base_path
2630

@@ -224,4 +228,4 @@ def self.add_predicate(xpath_query, predicate)
224228
return modified_query
225229
end
226230

227-
end
231+
end

spec/fixtures/mods_articles/hydrangea_article1.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
</titleInfo>
1212

1313
<name type="personal">
14+
Describes a person
1415
<namePart type="family">FAMILY NAME</namePart>
1516
<namePart type="given">GIVEN NAMES</namePart>
1617
<namePart type="termsOfAddress">DR.</namePart>

spec/unit/term_value_operators_spec.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
result.length.should == expected_values.length
1717
expected_values.each {|v| result.should include(v)}
1818
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
1923

2024
end
2125

@@ -72,7 +76,7 @@
7276
end
7377

7478
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(7).returns("//oxns:name[@type=\"personal\"][1]/oxns:role")
79+
OM::Samples::ModsArticle.terminology.expects(:xpath_with_indexes).with( *[{:person=>0}, :role]).times(10).returns("//oxns:name[@type=\"personal\"][1]/oxns:role")
7680
OM::Samples::ModsArticle.terminology.stubs(:xpath_with_indexes).with( *[{:person=>0}]).returns("//oxns:name[@type=\"personal\"][1]")
7781
@article.update_values( { [{":person"=>"0"}, "role"]=>"the role" } )
7882
@article.update_values( { [{"person"=>"0"}, "role"]=>"the role" } )
@@ -183,6 +187,13 @@
183187
@article.update_values({[:journal, :title_info]=>{"0"=>:delete}})
184188
@article.term_values(:journal, :title_info).should == ['mork']
185189
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 == 26
196+
end
186197

187198
end
188199

@@ -406,4 +417,4 @@
406417
end
407418
end
408419

409-
end
420+
end

spec/unit/term_xpath_generator_spec.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@
5151
@test_term.namespace_prefix = nil
5252
OM::XML::TermXpathGenerator.generate_relative_xpath(@test_term).should == 'namePart[@type="termsOfAddress"]'
5353
end
54+
55+
it "should not use a namespace for a path set to text() and should include normalize-space to ignore white space" do
56+
text_term = OM::XML::Term.new(:title_content, :path=>"text()")
57+
OM::XML::TermXpathGenerator.generate_relative_xpath(text_term).should == 'text()[normalize-space(.)]'
58+
end
59+
5460
end
5561

5662
describe "generate_absolute_xpath" do
@@ -108,4 +114,4 @@
108114
OM::XML::TermXpathGenerator.generate_constrained_xpath(@test_term_with_default_path).should == '//oxns:detail[contains(oxns:number[@type="volume"], "#{constraint_value}")]'.gsub('"', '\"')
109115
end
110116

111-
end
117+
end

0 commit comments

Comments
 (0)