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
XML::Reader.attributes now returns namespaces. refactored 
XML::Node.attributes along the way.
mdalessio (author)
Thu Sep 25 13:21:58 -0700 2008
commit  c5e7c3771b2bee6393360988fbfdc88ae440ec64
tree    99dd1da3b8e47e979f48b7437701996553e97358
parent  32f8a7f93969ddeade595af7e4039b5c49247c3e
...
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
 
 
176
177
178
...
439
440
441
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
442
443
444
...
158
159
160
 
161
 
162
163
164
165
 
 
 
 
 
 
 
 
166
167
168
169
170
...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
0
@@ -158,21 +158,13 @@ static VALUE attributes(VALUE self)
0
 {
0
     /* this code in the mode of xmlHasProp() */
0
     xmlNodePtr node ;
0
- xmlAttrPtr prop;
0
     VALUE attr ;
0
- xmlChar* propstr ;
0
 
0
     attr = rb_hash_new() ;
0
     Data_Get_Struct(self, xmlNode, node);
0
 
0
- prop = node->properties ;
0
- while (prop != NULL) {
0
- propstr = xmlGetProp(node, prop->name) ;
0
- rb_hash_aset(attr, rb_str_new2((const char*)prop->name),
0
- rb_str_new2((char*)propstr));
0
- xmlFree(propstr);
0
- prop = prop->next ;
0
- }
0
+ Nokogiri_xml_node_properties(node, attr);
0
+
0
     return attr ;
0
 }
0
 
0
@@ -439,6 +431,57 @@ VALUE Nokogiri_wrap_xml_node(xmlNodePtr node)
0
   return rb_node ;
0
 }
0
 
0
+
0
+void Nokogiri_xml_node_properties(xmlNodePtr node, VALUE attr_hash)
0
+{
0
+ xmlAttrPtr prop;
0
+ xmlChar* propstr ;
0
+ prop = node->properties ;
0
+ while (prop != NULL) {
0
+ propstr = xmlGetProp(node, prop->name) ;
0
+ rb_hash_aset(attr_hash, rb_str_new2((const char*)prop->name),
0
+ rb_str_new2((char*)propstr));
0
+ xmlFree(propstr);
0
+ prop = prop->next ;
0
+ }
0
+}
0
+
0
+
0
+#define XMLNS_PREFIX "xmlns"
0
+#define XMLNS_PREFIX_LEN 6 /* including either colon or \0 */
0
+#define XMLNS_BUFFER_LEN 128
0
+void Nokogiri_xml_node_namespaces(xmlNodePtr node, VALUE attr_hash)
0
+{
0
+ xmlNsPtr ns;
0
+ static char buffer[XMLNS_BUFFER_LEN] ;
0
+ char *key ;
0
+ size_t keylen ;
0
+
0
+ ns = node->nsDef;
0
+ while (ns != NULL) {
0
+
0
+ keylen = XMLNS_PREFIX_LEN + (ns->prefix ? (strlen((const char*)ns->prefix) + 1) : 0) ;
0
+ if (keylen > XMLNS_BUFFER_LEN) {
0
+ key = (char*)malloc(keylen) ;
0
+ } else {
0
+ key = buffer ;
0
+ }
0
+
0
+ if (ns->prefix) {
0
+ sprintf(key, "%s:%s", XMLNS_PREFIX, ns->prefix);
0
+ } else {
0
+ sprintf(key, "%s", XMLNS_PREFIX);
0
+ }
0
+
0
+ rb_hash_aset(attr_hash, rb_str_new2(key), rb_str_new2((const char*)ns->href)) ;
0
+ if (key != buffer) {
0
+ free(key);
0
+ }
0
+ ns = ns->next ;
0
+ }
0
+}
0
+
0
+
0
 VALUE cNokogiriXmlNode ;
0
 void init_xml_node()
0
 {
...
8
9
10
 
 
11
...
8
9
10
11
12
13
0
@@ -8,4 +8,6 @@ VALUE Nokogiri_wrap_xml_node(xmlNodePtr root);
0
 
0
 extern VALUE cNokogiriXmlNode ;
0
 VALUE Nokogiri_wrap_xml_node(xmlNodePtr node) ;
0
+void Nokogiri_xml_node_properties(xmlNodePtr node, VALUE attr_hash) ;
0
+void Nokogiri_xml_node_namespaces(xmlNodePtr node, VALUE attr_hash) ;
0
 #endif
...
65
66
67
 
 
68
69
 
 
70
71
 
72
73
74
75
76
77
 
 
 
 
78
79
80
...
65
66
67
68
69
70
71
72
73
74
 
75
76
77
78
79
 
 
80
81
82
83
84
85
86
0
@@ -65,16 +65,22 @@ static VALUE attributes_eh(VALUE self)
0
 static VALUE attributes(VALUE self)
0
 {
0
   xmlTextReaderPtr reader;
0
+ VALUE attr ;
0
+
0
   Data_Get_Struct(self, xmlTextReader, reader);
0
 
0
+ attr = rb_hash_new() ;
0
+
0
   if (! xmlTextReaderHasAttributes(reader))
0
- return rb_hash_new();
0
+ return attr ;
0
 
0
   xmlNodePtr ptr = xmlTextReaderExpand(reader);
0
   if(ptr == NULL) return Qnil;
0
 
0
- VALUE rb_node = Data_Wrap_Struct(cNokogiriXmlNode, 0, 0, ptr);
0
- return rb_funcall(rb_node, rb_intern("attributes"), 0);
0
+ Nokogiri_xml_node_namespaces(ptr, attr);
0
+ Nokogiri_xml_node_properties(ptr, attr);
0
+
0
+ return attr ;
0
 }
0
 
0
 /*
...
31
32
33
34
35
 
36
37
38
39
40
41
 
 
 
42
43
44
45
46
 
 
 
 
 
47
48
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
51
52
...
31
32
33
 
 
34
35
36
37
38
39
 
40
41
42
43
44
45
46
 
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
0
@@ -31,22 +31,42 @@ class TestReader < Nokogiri::TestCase
0
     </x>
0
     eoxml
0
     assert_equal false, reader.attributes?
0
- # TODO: xmlTextReaderHasAttributes considers namespace to be an attribute.
0
- assert_equal [false, false, true, false, true, false, false],
0
+ assert_equal [true, false, true, false, true, false, true],
0
       reader.map { |x| x.attributes? }
0
   end
0
 
0
   def test_attributes
0
     reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
0
- <x xmlns:tenderlove='http://tenderlovemaking.com/'>
0
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'
0
+ xmlns='http://mothership.connection.com/'
0
+ >
0
       <tenderlove:foo awesome='true'>snuggles!</tenderlove:foo>
0
     </x>
0
     eoxml
0
     assert_equal({}, reader.attributes)
0
- assert_equal [{}, {}, {"awesome"=>"true"}, {}, {"awesome"=>"true"}, {}, {}],
0
+ assert_equal [{'xmlns:tenderlove'=>'http://tenderlovemaking.com/',
0
+ 'xmlns'=>'http://mothership.connection.com/'},
0
+ {}, {"awesome"=>"true"}, {}, {"awesome"=>"true"}, {},
0
+ {'xmlns:tenderlove'=>'http://tenderlovemaking.com/',
0
+ 'xmlns'=>'http://mothership.connection.com/'}],
0
       reader.map { |x| x.attributes }
0
   end
0
 
0
+ def test_attribute_roundtrip
0
+ reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
0
+ <x xmlns:tenderlove='http://tenderlovemaking.com/'
0
+ xmlns='http://mothership.connection.com/'
0
+ >
0
+ <tenderlove:foo awesome='true' size='giant'>snuggles!</tenderlove:foo>
0
+ </x>
0
+ eoxml
0
+ reader.each do |node|
0
+ node.attributes.each do |key, value|
0
+ assert_equal value, node.attribute(key)
0
+ end
0
+ end
0
+ end
0
+
0
   def test_attribute_at
0
     reader = Nokogiri::XML::Reader.from_memory(<<-eoxml)
0
     <x xmlns:tenderlove='http://tenderlovemaking.com/'>

Comments

    No one has commented yet.