Skip to content

Commit be60281

Browse files
authored
Merge pull request Empact#49 from chewi/master
Namespacify all elements of an XPath, not just the first
2 parents 899b540 + 13017ec commit be60281

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 < ArgumentError # :nodoc:
35
end
@@ -52,12 +54,24 @@ def conventionize(what)
5254
end
5355

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

6377
def apply_blocks(val)

‎spec/xml/namespace_spec.rb‎

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

129141
context "with a default namespace declared" do
@@ -138,6 +150,8 @@ class DefaultNamespaceyObject
138150
xml_reader :default_namespace_with_namespaceless_from_and_explicit_namespace, :from => 'with_namespaceless_from', :namespace => 'explicit'
139151
xml_reader :default_namespace_with_namespaceless_from_and_namespace_false, :from => 'with_namespaceless_from', :namespace => false
140152
xml_reader :default_namespace_with_namespacey_from, :from => 'namespacey:with_namespacey_from'
153+
xml_reader :default_namespace_with_namespacey_xpath_from, :from => 'xpath/namespacey:default_namespace'
154+
xml_reader :default_namespace_with_xpath_from, :from => 'xpath/default_namespace'
141155

142156
# These are handled in the "roxml namespacey declaration" shared spec
143157
# xml_reader :default_namespace_with_namespacey_from_and_namespace_false, :from => 'namespacey:with_namespaceless_from', :namespace => false
@@ -154,6 +168,8 @@ class DefaultNamespaceyObject
154168
<default_declared:with_namespaceless_from>default namespace node</default_declared:with_namespaceless_from>
155169
<explicit:default_and_explicit_namespace>explicit namespace node</explicit:default_and_explicit_namespace>
156170
<default_namespace_with_namespace_false>namespaceless node</default_namespace_with_namespace_false>
171+
<default_declared:xpath><namespacey:default_namespace>namespacey xpath node</namespacey:default_namespace></default_declared:xpath>
172+
<default_declared:xpath><default_declared:default_namespace>default namespace with xpath node</default_declared:default_namespace></default_declared:xpath>
157173
</book>
158174
})
159175
end
@@ -171,6 +187,8 @@ class XmlDefaultNamespaceyObject
171187
xml_reader :default_namespace_with_namespaceless_from_and_explicit_namespace, :from => 'with_namespaceless_from', :namespace => 'explicit'
172188
xml_reader :default_namespace_with_namespaceless_from_and_namespace_false, :from => 'with_namespaceless_from', :namespace => false
173189
xml_reader :default_namespace_with_namespacey_from, :from => 'namespacey:with_namespacey_from'
190+
xml_reader :default_namespace_with_namespacey_xpath_from, :from => 'xpath/namespacey:default_namespace'
191+
xml_reader :default_namespace_with_xpath_from, :from => 'xpath/default_namespace'
174192

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

0 commit comments

Comments
 (0)