public
Description: Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser with XPath and CSS selector support.
Homepage: http://nokogiri.rubyforge.org/
Clone URL: git://github.com/tenderlove/nokogiri.git
support for xml namespaces.
mdalessio (author)
Wed Oct 01 12:51:28 -0700 2008
commit  f61e900ba179971799549122cc3df42934f82287
tree    db4df3d1b49d043c2666078fe302a2ac7400c1c2
parent  dcbae2f141665a10473162eb2e8feab7114383bd
...
63
64
65
 
66
67
68
...
63
64
65
66
67
68
69
0
@@ -63,6 +63,7 @@ lib/nokogiri/xml/sax/document.rb
0
 lib/nokogiri/xml/sax/parser.rb
0
 lib/nokogiri/xml/text.rb
0
 lib/nokogiri/xml/xpath.rb
0
+lib/nokogiri/xml/xpath_context.rb
0
 lib/nokogiri/xslt.rb
0
 lib/nokogiri/xslt/stylesheet.rb
0
 nokogiri.gemspec
...
207
208
209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
210
211
212
...
503
504
505
 
 
506
507
508
...
562
563
564
 
565
566
567
...
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
...
523
524
525
526
527
528
529
530
...
584
585
586
587
588
589
590
0
@@ -207,6 +207,26 @@ static VALUE attributes(VALUE self)
0
 }
0
 
0
 /*
0
+ * call-seq
0
+ * namespaces()
0
+ *
0
+ * returns a hash containing the node's namespaces.
0
+ */
0
+static VALUE namespaces(VALUE self)
0
+{
0
+ /* this code in the mode of xmlHasProp() */
0
+ xmlNodePtr node ;
0
+ VALUE attr ;
0
+
0
+ attr = rb_hash_new() ;
0
+ Data_Get_Struct(self, xmlNode, node);
0
+
0
+ Nokogiri_xml_node_namespaces(node, attr);
0
+
0
+ return attr ;
0
+}
0
+
0
+/*
0
  * call-seq:
0
  * type
0
  *
0
@@ -503,6 +523,8 @@ void Nokogiri_xml_node_namespaces(xmlNodePtr node, VALUE attr_hash)
0
   char *key ;
0
   size_t keylen ;
0
 
0
+ if (node->type != XML_ELEMENT_NODE) return ;
0
+
0
   ns = node->nsDef;
0
   while (ns != NULL) {
0
 
0
@@ -562,6 +584,7 @@ void init_xml_node()
0
   rb_define_method(klass, "[]=", set, 2);
0
   rb_define_method(klass, "remove", remove_prop, 1);
0
   rb_define_method(klass, "attributes", attributes, 0);
0
+ rb_define_method(klass, "namespaces", namespaces, 0);
0
   rb_define_method(klass, "add_previous_sibling", add_previous_sibling, 1);
0
   rb_define_method(klass, "add_next_sibling", add_next_sibling, 1);
0
   rb_define_method(klass, "encode_special_chars", encode_special_chars, 1);
...
6
7
8
 
9
10
11
...
6
7
8
9
10
11
12
0
@@ -6,6 +6,7 @@ require 'nokogiri/xml/text'
0
 require 'nokogiri/xml/document'
0
 require 'nokogiri/xml/node_set'
0
 require 'nokogiri/xml/xpath'
0
+require 'nokogiri/xml/xpath_context'
0
 require 'nokogiri/xml/builder'
0
 require 'nokogiri/xml/reader'
0
 
...
17
18
19
 
 
 
 
20
21
22
...
17
18
19
20
21
22
23
24
25
26
0
@@ -17,6 +17,10 @@ module Nokogiri
0
       def to_xml
0
         serialize
0
       end
0
+
0
+ def namespaces
0
+ root.collect_namespaces
0
+ end
0
     end
0
   end
0
 end
...
44
45
46
47
 
 
 
48
49
50
...
157
158
159
 
 
 
 
 
 
 
 
 
 
 
 
 
160
161
162
...
44
45
46
 
47
48
49
50
51
52
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
0
@@ -44,7 +44,9 @@ module Nokogiri
0
 
0
       def find_by_xpath *paths
0
         sets = paths.map { |path|
0
- set = XPathContext.new(self).evaluate(path).node_set
0
+ ctx = XPathContext.new(self)
0
+ ctx.register_namespaces(document.namespaces)
0
+ set = ctx.evaluate(path).node_set
0
           set.document = document
0
           document.decorate(set)
0
           set
0
@@ -157,6 +159,19 @@ module Nokogiri
0
       def xpath
0
         path
0
       end
0
+
0
+ # recursively get all namespaces from this node and its subtree
0
+ def collect_namespaces
0
+ # TODO: print warning message if a prefix refers to more than one URI in the document?
0
+ ns = {}
0
+ traverse {|j| ns.merge!(j.namespaces)}
0
+ ns
0
+ end
0
+
0
+ def traverse(&block)
0
+ children.each{|j| j.traverse(&block) }
0
+ block.call(self)
0
+ end
0
     end
0
   end
0
 end
...
143
144
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
147
148
...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
0
@@ -143,6 +143,36 @@ module Nokogiri
0
         assert_equal set[0].to_xml, second.to_xml
0
       end
0
 
0
+ def test_namespaces
0
+ xml = Nokogiri::XML.parse(<<-EOF)
0
+<x xmlns:a='http://foo.com/' xmlns:b='http://bar.com/'>
0
+ <y xmlns:c='http://bazz.com/'>
0
+ <a:div>hello a</a:div>
0
+ <b:div>hello b</b:div>
0
+ <c:div>hello c</c:div>
0
+ </y>
0
+</x>
0
+EOF
0
+ assert namespaces = xml.root.namespaces
0
+ assert namespaces.key?('xmlns:a')
0
+ assert_equal 'http://foo.com/', namespaces['xmlns:a']
0
+ assert namespaces.key?('xmlns:b')
0
+ assert_equal 'http://bar.com/', namespaces['xmlns:b']
0
+ assert ! namespaces.key?('xmlns:c')
0
+
0
+ assert namespaces = xml.namespaces
0
+ assert namespaces.key?('xmlns:a')
0
+ assert_equal 'http://foo.com/', namespaces['xmlns:a']
0
+ assert namespaces.key?('xmlns:b')
0
+ assert_equal 'http://bar.com/', namespaces['xmlns:b']
0
+ assert namespaces.key?('xmlns:c')
0
+ assert_equal 'http://bazz.com/', namespaces['xmlns:c']
0
+
0
+ assert_equal "hello a", xml.search("//a:div").first.inner_text
0
+ assert_equal "hello b", xml.search("//b:div").first.inner_text
0
+ assert_equal "hello c", xml.search("//c:div").first.inner_text
0
+ end
0
+
0
     end
0
   end
0
 end

Comments

    No one has commented yet.