Skip to content

Commit 13017ec

Browse files
committed
Namespacify all elements of an XPath, not just the first
1 parent 076f78c commit 13017ec

2 files changed

Lines changed: 38 additions & 4 deletions

File tree

‎lib/roxml/xml/references.rb‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
require "rexml/xpath_parser"
2+
13
module ROXML
24
class RequiredElementMissing < Exception # :nodoc:
35
end
@@ -50,12 +52,24 @@ def conventionize(what)
5052
end
5153

5254
def namespacify(what)
53-
if what.to_s.present? && !what.to_s.include?(':') && opts.namespace != false
54-
[opts.namespace, @instance.class.roxml_namespace, @default_namespace].each do |namespace|
55-
return opts.namespace == '*' ? (what == '*' ? "*" : "*[local-name()='#{what}']") : "#{namespace}:#{what}" if namespace
55+
if what.to_s.present? && opts.namespace != false && ns = [opts.namespace, @instance.class.roxml_namespace, @default_namespace].compact.map(&:to_s).first
56+
parser = REXML::Parsers::XPathParser.new
57+
parsed = parser.parse what
58+
59+
parsed.each_cons(4).with_index.each do |a,i|
60+
if a[0..2] == [:child, :qname, ""]
61+
if ns == "*"
62+
parsed[i+1,3] = [:any, :predicate, [:eq, [:function, "local-name", []], [:literal, a[3]]]] if a[3] != "*"
63+
else
64+
a[2].replace ns
65+
end
66+
end
5667
end
68+
69+
parser.abbreviate parsed
70+
else
71+
what
5772
end
58-
what
5973
end
6074

6175
def apply_blocks(val)

‎spec/xml/namespace_spec.rb‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ class VApp
125125
@instance.default_namespace_with_namespacey_from.should == 'namespacey node'
126126
end
127127
end
128+
129+
context "with an namespacey XPath :from" do
130+
it "should use the given namespace" do
131+
@instance.default_namespace_with_namespacey_xpath_from.should == 'namespacey xpath node'
132+
end
133+
end
134+
135+
context "with an XPath :from" do
136+
it "should use the default namespace" do
137+
@instance.default_namespace_with_xpath_from.should == 'default namespace with xpath node'
138+
end
139+
end
128140
end
129141

130142
context "with a default namespace declared" do
@@ -139,6 +151,8 @@ class DefaultNamespaceyObject
139151
xml_reader :default_namespace_with_namespaceless_from_and_explicit_namespace, :from => 'with_namespaceless_from', :namespace => 'explicit'
140152
xml_reader :default_namespace_with_namespaceless_from_and_namespace_false, :from => 'with_namespaceless_from', :namespace => false
141153
xml_reader :default_namespace_with_namespacey_from, :from => 'namespacey:with_namespacey_from'
154+
xml_reader :default_namespace_with_namespacey_xpath_from, :from => 'xpath/namespacey:default_namespace'
155+
xml_reader :default_namespace_with_xpath_from, :from => 'xpath/default_namespace'
142156

143157
# These are handled in the "roxml namespacey declaration" shared spec
144158
# xml_reader :default_namespace_with_namespacey_from_and_namespace_false, :from => 'namespacey:with_namespaceless_from', :namespace => false
@@ -155,6 +169,8 @@ class DefaultNamespaceyObject
155169
<default_declared:with_namespaceless_from>default namespace node</default_declared:with_namespaceless_from>
156170
<explicit:default_and_explicit_namespace>explicit namespace node</explicit:default_and_explicit_namespace>
157171
<default_namespace_with_namespace_false>namespaceless node</default_namespace_with_namespace_false>
172+
<default_declared:xpath><namespacey:default_namespace>namespacey xpath node</namespacey:default_namespace></default_declared:xpath>
173+
<default_declared:xpath><default_declared:default_namespace>default namespace with xpath node</default_declared:default_namespace></default_declared:xpath>
158174
</book>
159175
})
160176
end
@@ -172,6 +188,8 @@ class XmlDefaultNamespaceyObject
172188
xml_reader :default_namespace_with_namespaceless_from_and_explicit_namespace, :from => 'with_namespaceless_from', :namespace => 'explicit'
173189
xml_reader :default_namespace_with_namespaceless_from_and_namespace_false, :from => 'with_namespaceless_from', :namespace => false
174190
xml_reader :default_namespace_with_namespacey_from, :from => 'namespacey:with_namespacey_from'
191+
xml_reader :default_namespace_with_namespacey_xpath_from, :from => 'xpath/namespacey:default_namespace'
192+
xml_reader :default_namespace_with_xpath_from, :from => 'xpath/default_namespace'
175193

176194
# These are handled in the "roxml namespacey declaration" shared spec
177195
# xml_reader :default_namespace_with_namespacey_from_and_namespace_false, :from => 'namespacey:with_namespaceless_from', :namespace => false
@@ -188,6 +206,8 @@ class XmlDefaultNamespaceyObject
188206
<with_namespaceless_from>default namespace node</with_namespaceless_from>
189207
<explicit:default_and_explicit_namespace>explicit namespace node</explicit:default_and_explicit_namespace>
190208
<default_namespace_with_namespace_false xmlns="">namespaceless node</default_namespace_with_namespace_false>
209+
<xpath><namespacey:default_namespace>namespacey xpath node</namespacey:default_namespace></xpath>
210+
<xpath><default_namespace>default namespace with xpath node</default_namespace></xpath>
191211
</book>
192212
})
193213
end

0 commit comments

Comments
 (0)