nokogiri 1.12.5 → 1.13.10

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of nokogiri might be problematic. Click here for more details.

Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +2 -0
  3. data/README.md +9 -7
  4. data/bin/nokogiri +63 -50
  5. data/dependencies.yml +13 -64
  6. data/ext/nokogiri/extconf.rb +81 -46
  7. data/ext/nokogiri/gumbo.c +1 -1
  8. data/ext/nokogiri/html4_sax_parser_context.c +2 -3
  9. data/ext/nokogiri/nokogiri.h +9 -0
  10. data/ext/nokogiri/xml_attr.c +2 -2
  11. data/ext/nokogiri/xml_attribute_decl.c +3 -3
  12. data/ext/nokogiri/xml_cdata.c +1 -1
  13. data/ext/nokogiri/xml_document.c +41 -37
  14. data/ext/nokogiri/xml_document_fragment.c +0 -2
  15. data/ext/nokogiri/xml_dtd.c +10 -10
  16. data/ext/nokogiri/xml_element_decl.c +3 -3
  17. data/ext/nokogiri/xml_encoding_handler.c +25 -11
  18. data/ext/nokogiri/xml_entity_decl.c +5 -5
  19. data/ext/nokogiri/xml_namespace.c +41 -5
  20. data/ext/nokogiri/xml_node.c +708 -382
  21. data/ext/nokogiri/xml_node_set.c +4 -4
  22. data/ext/nokogiri/xml_reader.c +92 -11
  23. data/ext/nokogiri/xml_sax_parser_context.c +10 -3
  24. data/ext/nokogiri/xml_schema.c +3 -3
  25. data/ext/nokogiri/xml_text.c +1 -1
  26. data/ext/nokogiri/xml_xpath_context.c +76 -50
  27. data/ext/nokogiri/xslt_stylesheet.c +107 -9
  28. data/gumbo-parser/src/parser.c +0 -11
  29. data/lib/nokogiri/class_resolver.rb +67 -0
  30. data/lib/nokogiri/css/node.rb +9 -8
  31. data/lib/nokogiri/css/parser.rb +360 -341
  32. data/lib/nokogiri/css/parser.y +249 -244
  33. data/lib/nokogiri/css/parser_extras.rb +22 -20
  34. data/lib/nokogiri/css/syntax_error.rb +1 -0
  35. data/lib/nokogiri/css/tokenizer.rb +4 -3
  36. data/lib/nokogiri/css/tokenizer.rex +3 -2
  37. data/lib/nokogiri/css/xpath_visitor.rb +179 -82
  38. data/lib/nokogiri/css.rb +38 -6
  39. data/lib/nokogiri/decorators/slop.rb +8 -7
  40. data/lib/nokogiri/extension.rb +1 -1
  41. data/lib/nokogiri/gumbo.rb +1 -0
  42. data/lib/nokogiri/html.rb +16 -10
  43. data/lib/nokogiri/html4/builder.rb +1 -0
  44. data/lib/nokogiri/html4/document.rb +88 -77
  45. data/lib/nokogiri/html4/document_fragment.rb +11 -7
  46. data/lib/nokogiri/html4/element_description.rb +1 -0
  47. data/lib/nokogiri/html4/element_description_defaults.rb +426 -520
  48. data/lib/nokogiri/html4/entity_lookup.rb +2 -1
  49. data/lib/nokogiri/html4/sax/parser.rb +5 -2
  50. data/lib/nokogiri/html4/sax/parser_context.rb +1 -0
  51. data/lib/nokogiri/html4/sax/push_parser.rb +7 -7
  52. data/lib/nokogiri/html4.rb +11 -5
  53. data/lib/nokogiri/html5/document.rb +27 -10
  54. data/lib/nokogiri/html5/document_fragment.rb +5 -2
  55. data/lib/nokogiri/html5/node.rb +10 -3
  56. data/lib/nokogiri/html5.rb +69 -64
  57. data/lib/nokogiri/jruby/dependencies.rb +10 -9
  58. data/lib/nokogiri/syntax_error.rb +1 -0
  59. data/lib/nokogiri/version/constant.rb +2 -1
  60. data/lib/nokogiri/version/info.rb +20 -13
  61. data/lib/nokogiri/version.rb +1 -0
  62. data/lib/nokogiri/xml/attr.rb +5 -3
  63. data/lib/nokogiri/xml/attribute_decl.rb +2 -1
  64. data/lib/nokogiri/xml/builder.rb +34 -32
  65. data/lib/nokogiri/xml/cdata.rb +2 -1
  66. data/lib/nokogiri/xml/character_data.rb +1 -0
  67. data/lib/nokogiri/xml/document.rb +144 -103
  68. data/lib/nokogiri/xml/document_fragment.rb +41 -38
  69. data/lib/nokogiri/xml/dtd.rb +3 -2
  70. data/lib/nokogiri/xml/element_content.rb +1 -0
  71. data/lib/nokogiri/xml/element_decl.rb +2 -1
  72. data/lib/nokogiri/xml/entity_decl.rb +3 -2
  73. data/lib/nokogiri/xml/entity_reference.rb +1 -0
  74. data/lib/nokogiri/xml/namespace.rb +2 -0
  75. data/lib/nokogiri/xml/node/save_options.rb +8 -4
  76. data/lib/nokogiri/xml/node.rb +521 -351
  77. data/lib/nokogiri/xml/node_set.rb +50 -54
  78. data/lib/nokogiri/xml/notation.rb +12 -0
  79. data/lib/nokogiri/xml/parse_options.rb +12 -7
  80. data/lib/nokogiri/xml/pp/character_data.rb +8 -6
  81. data/lib/nokogiri/xml/pp/node.rb +24 -26
  82. data/lib/nokogiri/xml/pp.rb +1 -0
  83. data/lib/nokogiri/xml/processing_instruction.rb +2 -1
  84. data/lib/nokogiri/xml/reader.rb +20 -24
  85. data/lib/nokogiri/xml/relax_ng.rb +1 -0
  86. data/lib/nokogiri/xml/sax/document.rb +20 -19
  87. data/lib/nokogiri/xml/sax/parser.rb +37 -34
  88. data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
  89. data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
  90. data/lib/nokogiri/xml/sax.rb +1 -0
  91. data/lib/nokogiri/xml/schema.rb +7 -6
  92. data/lib/nokogiri/xml/searchable.rb +93 -62
  93. data/lib/nokogiri/xml/syntax_error.rb +5 -4
  94. data/lib/nokogiri/xml/text.rb +1 -0
  95. data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
  96. data/lib/nokogiri/xml/xpath.rb +12 -0
  97. data/lib/nokogiri/xml/xpath_context.rb +2 -3
  98. data/lib/nokogiri/xml.rb +4 -3
  99. data/lib/nokogiri/xslt/stylesheet.rb +1 -0
  100. data/lib/nokogiri/xslt.rb +21 -13
  101. data/lib/nokogiri.rb +19 -16
  102. data/lib/xsd/xmlparser/nokogiri.rb +25 -24
  103. data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
  104. data/patches/libxslt/0001-update-automake-files-for-arm64.patch +2445 -1919
  105. data/ports/archives/libxml2-2.10.3.tar.xz +0 -0
  106. data/ports/archives/libxslt-1.1.37.tar.xz +0 -0
  107. metadata +117 -34
  108. data/patches/libxml2/0004-use-glibc-strlen.patch +0 -53
  109. data/patches/libxml2/0006-update-automake-files-for-arm64.patch +0 -2511
  110. data/patches/libxml2/0007-Fix-XPath-recursion-limit.patch +0 -31
  111. data/patches/libxslt/0002-Fix-xml2-config-check-in-configure-script.patch +0 -19
  112. data/ports/archives/libxml2-2.9.12.tar.gz +0 -0
  113. data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
@@ -1,23 +1,30 @@
1
1
  #include <nokogiri.h>
2
2
 
3
- VALUE cNokogiriXmlNode ;
3
+ // :stopdoc:
4
4
 
5
+ VALUE cNokogiriXmlNode ;
5
6
  static ID id_decorate, id_decorate_bang;
6
7
 
8
+ typedef xmlNodePtr(*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
9
+
7
10
  #ifdef DEBUG
8
11
  static void
9
- debug_node_dealloc(xmlNodePtr x)
12
+ _xml_node_dealloc(xmlNodePtr x)
10
13
  {
11
14
  NOKOGIRI_DEBUG_START(x)
12
15
  NOKOGIRI_DEBUG_END(x)
13
16
  }
14
17
  #else
15
- # define debug_node_dealloc 0
18
+ # define _xml_node_dealloc 0
16
19
  #endif
17
20
 
18
21
  static void
19
- mark(xmlNodePtr node)
22
+ _xml_node_mark(xmlNodePtr node)
20
23
  {
24
+ if (!DOC_RUBY_OBJECT_TEST(node->doc)) {
25
+ return;
26
+ }
27
+
21
28
  xmlDocPtr doc = node->doc;
22
29
  if (doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE) {
23
30
  if (DOC_RUBY_OBJECT_TEST(doc)) {
@@ -28,10 +35,32 @@ mark(xmlNodePtr node)
28
35
  }
29
36
  }
30
37
 
31
- /* :nodoc: */
32
- typedef xmlNodePtr(*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
38
+ #ifdef HAVE_RB_GC_LOCATION
39
+ static void
40
+ _xml_node_update_references(xmlNodePtr node)
41
+ {
42
+ if (node->_private) {
43
+ node->_private = (void *)rb_gc_location((VALUE)node->_private);
44
+ }
45
+ }
46
+ #endif
47
+
48
+ typedef void (*gc_callback_t)(void *);
49
+
50
+ static const rb_data_type_t nokogiri_node_type = {
51
+ "Nokogiri/XMLNode",
52
+ {
53
+ (gc_callback_t)_xml_node_mark, (gc_callback_t)_xml_node_dealloc, 0,
54
+ #ifdef HAVE_RB_GC_LOCATION
55
+ (gc_callback_t)_xml_node_update_references
56
+ #endif
57
+ },
58
+ 0, 0,
59
+ #ifdef RUBY_TYPED_FREE_IMMEDIATELY
60
+ RUBY_TYPED_FREE_IMMEDIATELY,
61
+ #endif
62
+ };
33
63
 
34
- /* :nodoc: */
35
64
  static void
36
65
  relink_namespace(xmlNodePtr reparented)
37
66
  {
@@ -143,7 +172,9 @@ relink_namespace(xmlNodePtr reparented)
143
172
  }
144
173
  }
145
174
 
146
- /* :nodoc: */
175
+
176
+ /* internal function meant to wrap xmlReplaceNode
177
+ and fix some issues we have with libxml2 merging nodes */
147
178
  static xmlNodePtr
148
179
  xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
149
180
  {
@@ -168,7 +199,18 @@ xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
168
199
  return retval ;
169
200
  }
170
201
 
171
- /* :nodoc: */
202
+
203
+ static void
204
+ raise_if_ancestor_of_self(xmlNodePtr self)
205
+ {
206
+ for (xmlNodePtr ancestor = self->parent ; ancestor ; ancestor = ancestor->parent) {
207
+ if (self == ancestor) {
208
+ rb_raise(rb_eRuntimeError, "cycle detected: node '%s' is an ancestor of itself", self->name);
209
+ }
210
+ }
211
+ }
212
+
213
+
172
214
  static VALUE
173
215
  reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
174
216
  {
@@ -183,8 +225,8 @@ reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func
183
225
  rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
184
226
  }
185
227
 
186
- Data_Get_Struct(reparentee_obj, xmlNode, reparentee);
187
- Data_Get_Struct(pivot_obj, xmlNode, pivot);
228
+ Noko_Node_Get_Struct(reparentee_obj, xmlNode, reparentee);
229
+ Noko_Node_Get_Struct(pivot_obj, xmlNode, pivot);
188
230
 
189
231
  /*
190
232
  * Check if nodes given are appropriate to have a parent-child
@@ -357,49 +399,421 @@ ok:
357
399
  * adjacent text nodes.
358
400
  */
359
401
  DATA_PTR(reparentee_obj) = reparented ;
360
-
361
- relink_namespace(reparented);
362
-
363
402
  reparented_obj = noko_xml_node_wrap(Qnil, reparented);
364
403
 
365
404
  rb_funcall(reparented_obj, id_decorate_bang, 0);
366
405
 
406
+ /* if we've created a cycle, raise an exception */
407
+ raise_if_ancestor_of_self(reparented);
408
+
409
+ relink_namespace(reparented);
410
+
367
411
  return reparented_obj ;
368
412
  }
369
413
 
414
+ // :startdoc:
370
415
 
371
416
  /*
372
- * call-seq:
373
- * document
417
+ * :call-seq:
418
+ * add_namespace_definition(prefix, href) → Nokogiri::XML::Namespace
419
+ * add_namespace(prefix, href) → Nokogiri::XML::Namespace
420
+ *
421
+ * :category: Manipulating Document Structure
422
+ *
423
+ * Adds a namespace definition to this node with +prefix+ using +href+ value, as if this node had
424
+ * included an attribute "xmlns:prefix=href".
425
+ *
426
+ * A default namespace definition for this node can be added by passing +nil+ for +prefix+.
427
+ *
428
+ * [Parameters]
429
+ * - +prefix+ (String, +nil+) An {XML Name}[https://www.w3.org/TR/xml-names/#ns-decl]
430
+ * - +href+ (String) The {URI reference}[https://www.w3.org/TR/xml-names/#sec-namespaces]
431
+ *
432
+ * [Returns] The new Nokogiri::XML::Namespace
433
+ *
434
+ * *Example:* adding a non-default namespace definition
435
+ *
436
+ * doc = Nokogiri::XML("<store><inventory></inventory></store>")
437
+ * inventory = doc.at_css("inventory")
438
+ * inventory.add_namespace_definition("automobile", "http://alices-autos.com/")
439
+ * inventory.add_namespace_definition("bicycle", "http://bobs-bikes.com/")
440
+ * inventory.add_child("<automobile:tire>Michelin model XGV, size 75R</automobile:tire>")
441
+ * doc.to_xml
442
+ * # => "<?xml version=\"1.0\"?>\n" +
443
+ * # "<store>\n" +
444
+ * # " <inventory xmlns:automobile=\"http://alices-autos.com/\" xmlns:bicycle=\"http://bobs-bikes.com/\">\n" +
445
+ * # " <automobile:tire>Michelin model XGV, size 75R</automobile:tire>\n" +
446
+ * # " </inventory>\n" +
447
+ * # "</store>\n"
448
+ *
449
+ * *Example:* adding a default namespace definition
450
+ *
451
+ * doc = Nokogiri::XML("<store><inventory><tire>Michelin model XGV, size 75R</tire></inventory></store>")
452
+ * doc.at_css("tire").add_namespace_definition(nil, "http://bobs-bikes.com/")
453
+ * doc.to_xml
454
+ * # => "<?xml version=\"1.0\"?>\n" +
455
+ * # "<store>\n" +
456
+ * # " <inventory>\n" +
457
+ * # " <tire xmlns=\"http://bobs-bikes.com/\">Michelin model XGV, size 75R</tire>\n" +
458
+ * # " </inventory>\n" +
459
+ * # "</store>\n"
460
+ *
461
+ */
462
+ static VALUE
463
+ rb_xml_node_add_namespace_definition(VALUE rb_node, VALUE rb_prefix, VALUE rb_href)
464
+ {
465
+ xmlNodePtr c_node, element;
466
+ xmlNsPtr c_namespace;
467
+ const xmlChar *c_prefix = (const xmlChar *)(NIL_P(rb_prefix) ? NULL : StringValueCStr(rb_prefix));
468
+
469
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
470
+ element = c_node ;
471
+
472
+ c_namespace = xmlSearchNs(c_node->doc, c_node, c_prefix);
473
+
474
+ if (!c_namespace) {
475
+ if (c_node->type != XML_ELEMENT_NODE) {
476
+ element = c_node->parent;
477
+ }
478
+ c_namespace = xmlNewNs(element, (const xmlChar *)StringValueCStr(rb_href), c_prefix);
479
+ }
480
+
481
+ if (!c_namespace) {
482
+ return Qnil ;
483
+ }
484
+
485
+ if (NIL_P(rb_prefix) || c_node != element) {
486
+ xmlSetNs(c_node, c_namespace);
487
+ }
488
+
489
+ return noko_xml_namespace_wrap(c_namespace, c_node->doc);
490
+ }
491
+
492
+
493
+ /*
494
+ * :call-seq: attribute(name) → Nokogiri::XML::Attr
495
+ *
496
+ * :category: Working With Node Attributes
497
+ *
498
+ * [Returns] Attribute (Nokogiri::XML::Attr) belonging to this node with name +name+.
499
+ *
500
+ * ⚠ Note that attribute namespaces are ignored and only the simple (non-namespace-prefixed) name is
501
+ * used to find a matching attribute. In case of a simple name collision, only one of the matching
502
+ * attributes will be returned. In this case, you will need to use #attribute_with_ns.
503
+ *
504
+ * *Example:*
505
+ *
506
+ * doc = Nokogiri::XML("<root><child size='large' class='big wide tall'/></root>")
507
+ * child = doc.at_css("child")
508
+ * child.attribute("size") # => #<Nokogiri::XML::Attr:0x550 name="size" value="large">
509
+ * child.attribute("class") # => #<Nokogiri::XML::Attr:0x564 name="class" value="big wide tall">
510
+ *
511
+ * *Example* showing that namespaced attributes will not be returned:
512
+ *
513
+ * ⚠ Note that only one of the two matching attributes is returned.
514
+ *
515
+ * doc = Nokogiri::XML(<<~EOF)
516
+ * <root xmlns:width='http://example.com/widths'
517
+ * xmlns:height='http://example.com/heights'>
518
+ * <child width:size='broad' height:size='tall'/>
519
+ * </root>
520
+ * EOF
521
+ * doc.at_css("child").attribute("size")
522
+ * # => #(Attr:0x550 {
523
+ * # name = "size",
524
+ * # namespace = #(Namespace:0x564 {
525
+ * # prefix = "width",
526
+ * # href = "http://example.com/widths"
527
+ * # }),
528
+ * # value = "broad"
529
+ * # })
530
+ */
531
+ static VALUE
532
+ rb_xml_node_attribute(VALUE self, VALUE name)
533
+ {
534
+ xmlNodePtr node;
535
+ xmlAttrPtr prop;
536
+ Noko_Node_Get_Struct(self, xmlNode, node);
537
+ prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
538
+
539
+ if (! prop) { return Qnil; }
540
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
541
+ }
542
+
543
+
544
+ /*
545
+ * :call-seq: attribute_nodes() → Array<Nokogiri::XML::Attr>
546
+ *
547
+ * :category: Working With Node Attributes
548
+ *
549
+ * [Returns] Attributes (an Array of Nokogiri::XML::Attr) belonging to this node.
550
+ *
551
+ * Note that this is the preferred alternative to #attributes when the simple
552
+ * (non-namespace-prefixed) attribute names may collide.
553
+ *
554
+ * *Example:*
555
+ *
556
+ * Contrast this with the colliding-name example from #attributes.
557
+ *
558
+ * doc = Nokogiri::XML(<<~EOF)
559
+ * <root xmlns:width='http://example.com/widths'
560
+ * xmlns:height='http://example.com/heights'>
561
+ * <child width:size='broad' height:size='tall'/>
562
+ * </root>
563
+ * EOF
564
+ * doc.at_css("child").attribute_nodes
565
+ * # => [#(Attr:0x550 {
566
+ * # name = "size",
567
+ * # namespace = #(Namespace:0x564 {
568
+ * # prefix = "width",
569
+ * # href = "http://example.com/widths"
570
+ * # }),
571
+ * # value = "broad"
572
+ * # }),
573
+ * # #(Attr:0x578 {
574
+ * # name = "size",
575
+ * # namespace = #(Namespace:0x58c {
576
+ * # prefix = "height",
577
+ * # href = "http://example.com/heights"
578
+ * # }),
579
+ * # value = "tall"
580
+ * # })]
581
+ */
582
+ static VALUE
583
+ rb_xml_node_attribute_nodes(VALUE rb_node)
584
+ {
585
+ xmlNodePtr c_node;
586
+
587
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
588
+
589
+ return noko_xml_node_attrs(c_node);
590
+ }
591
+
592
+
593
+ /*
594
+ * :call-seq: attribute_with_ns(name, namespace) → Nokogiri::XML::Attr
595
+ *
596
+ * :category: Working With Node Attributes
597
+ *
598
+ * [Returns]
599
+ * Attribute (Nokogiri::XML::Attr) belonging to this node with matching +name+ and +namespace+.
600
+ *
601
+ * [Parameters]
602
+ * - +name+ (String): the simple (non-namespace-prefixed) name of the attribute
603
+ * - +namespace+ (String): the URI of the attribute's namespace
604
+ *
605
+ * See related: #attribute
606
+ *
607
+ * *Example:*
608
+ *
609
+ * doc = Nokogiri::XML(<<~EOF)
610
+ * <root xmlns:width='http://example.com/widths'
611
+ * xmlns:height='http://example.com/heights'>
612
+ * <child width:size='broad' height:size='tall'/>
613
+ * </root>
614
+ * EOF
615
+ * doc.at_css("child").attribute_with_ns("size", "http://example.com/widths")
616
+ * # => #(Attr:0x550 {
617
+ * # name = "size",
618
+ * # namespace = #(Namespace:0x564 {
619
+ * # prefix = "width",
620
+ * # href = "http://example.com/widths"
621
+ * # }),
622
+ * # value = "broad"
623
+ * # })
624
+ * doc.at_css("child").attribute_with_ns("size", "http://example.com/heights")
625
+ * # => #(Attr:0x578 {
626
+ * # name = "size",
627
+ * # namespace = #(Namespace:0x58c {
628
+ * # prefix = "height",
629
+ * # href = "http://example.com/heights"
630
+ * # }),
631
+ * # value = "tall"
632
+ * # })
633
+ */
634
+ static VALUE
635
+ rb_xml_node_attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
636
+ {
637
+ xmlNodePtr node;
638
+ xmlAttrPtr prop;
639
+ Noko_Node_Get_Struct(self, xmlNode, node);
640
+ prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
641
+ NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
642
+
643
+ if (! prop) { return Qnil; }
644
+ return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
645
+ }
646
+
647
+
648
+
649
+ /*
650
+ * call-seq: blank? → Boolean
651
+ *
652
+ * [Returns] +true+ if the node is an empty or whitespace-only text or cdata node, else +false+.
653
+ *
654
+ * *Example:*
655
+ *
656
+ * Nokogiri("<root><child/></root>").root.child.blank? # => false
657
+ * Nokogiri("<root>\t \n</root>").root.child.blank? # => true
658
+ * Nokogiri("<root><![CDATA[\t \n]]></root>").root.child.blank? # => true
659
+ * Nokogiri("<root>not-blank</root>").root.child
660
+ * .tap { |n| n.content = "" }.blank # => true
661
+ */
662
+ static VALUE
663
+ rb_xml_node_blank_eh(VALUE self)
664
+ {
665
+ xmlNodePtr node;
666
+ Noko_Node_Get_Struct(self, xmlNode, node);
667
+ return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
668
+ }
669
+
670
+
671
+ /*
672
+ * :call-seq: child() → Nokogiri::XML::Node
673
+ *
674
+ * :category: Traversing Document Structure
675
+ *
676
+ * [Returns] First of this node's children, or +nil+ if there are no children
677
+ *
678
+ * This is a convenience method and is equivalent to:
679
+ *
680
+ * node.children.first
681
+ *
682
+ * See related: #children
683
+ */
684
+ static VALUE
685
+ rb_xml_node_child(VALUE self)
686
+ {
687
+ xmlNodePtr node, child;
688
+ Noko_Node_Get_Struct(self, xmlNode, node);
689
+
690
+ child = node->children;
691
+ if (!child) { return Qnil; }
692
+
693
+ return noko_xml_node_wrap(Qnil, child);
694
+ }
695
+
696
+
697
+ /*
698
+ * :call-seq: children() → Nokogiri::XML::NodeSet
699
+ *
700
+ * :category: Traversing Document Structure
701
+ *
702
+ * [Returns] Nokogiri::XML::NodeSet containing this node's children.
703
+ */
704
+ static VALUE
705
+ rb_xml_node_children(VALUE self)
706
+ {
707
+ xmlNodePtr node;
708
+ xmlNodePtr child;
709
+ xmlNodeSetPtr set;
710
+ VALUE document;
711
+ VALUE node_set;
712
+
713
+ Noko_Node_Get_Struct(self, xmlNode, node);
714
+
715
+ child = node->children;
716
+ set = xmlXPathNodeSetCreate(child);
717
+
718
+ document = DOC_RUBY_OBJECT(node->doc);
719
+
720
+ if (!child) { return noko_xml_node_set_wrap(set, document); }
721
+
722
+ child = child->next;
723
+ while (NULL != child) {
724
+ xmlXPathNodeSetAddUnique(set, child);
725
+ child = child->next;
726
+ }
727
+
728
+ node_set = noko_xml_node_set_wrap(set, document);
729
+
730
+ return node_set;
731
+ }
732
+
733
+
734
+ /*
735
+ * :call-seq:
736
+ * content() → String
737
+ * inner_text() → String
738
+ * text() → String
739
+ * to_str() → String
740
+ *
741
+ * [Returns]
742
+ * Contents of all the text nodes in this node's subtree, concatenated together into a single
743
+ * String.
744
+ *
745
+ * ⚠ Note that entities will _always_ be expanded in the returned String.
746
+ *
747
+ * See related: #inner_html
748
+ *
749
+ * *Example* of how entities are handled:
750
+ *
751
+ * Note that <tt>&lt;</tt> becomes <tt><</tt> in the returned String.
752
+ *
753
+ * doc = Nokogiri::XML.fragment("<child>a &lt; b</child>")
754
+ * doc.at_css("child").content
755
+ * # => "a < b"
756
+ *
757
+ * *Example* of how a subtree is handled:
758
+ *
759
+ * Note that the <tt><span></tt> tags are omitted and only the text node contents are returned,
760
+ * concatenated into a single string.
761
+ *
762
+ * doc = Nokogiri::XML.fragment("<child><span>first</span> <span>second</span></child>")
763
+ * doc.at_css("child").content
764
+ * # => "first second"
765
+ */
766
+ static VALUE
767
+ rb_xml_node_content(VALUE self)
768
+ {
769
+ xmlNodePtr node;
770
+ xmlChar *content;
771
+
772
+ Noko_Node_Get_Struct(self, xmlNode, node);
773
+
774
+ content = xmlNodeGetContent(node);
775
+ if (content) {
776
+ VALUE rval = NOKOGIRI_STR_NEW2(content);
777
+ xmlFree(content);
778
+ return rval;
779
+ }
780
+ return Qnil;
781
+ }
782
+
783
+
784
+ /*
785
+ * :call-seq: document() → Nokogiri::XML::Document
786
+ *
787
+ * :category: Traversing Document Structure
374
788
  *
375
- * Get the document for this Node
789
+ * [Returns] Parent Nokogiri::XML::Document for this node
376
790
  */
377
791
  static VALUE
378
- document(VALUE self)
792
+ rb_xml_node_document(VALUE self)
379
793
  {
380
794
  xmlNodePtr node;
381
- Data_Get_Struct(self, xmlNode, node);
795
+ Noko_Node_Get_Struct(self, xmlNode, node);
382
796
  return DOC_RUBY_OBJECT(node->doc);
383
797
  }
384
798
 
385
799
  /*
386
- * call-seq:
387
- * pointer_id
800
+ * :call-seq: pointer_id() → Integer
388
801
  *
389
- * Get the internal pointer number
802
+ * [Returns]
803
+ * A unique id for this node based on the internal memory structures. This method is used by #==
804
+ * to determine node identity.
390
805
  */
391
806
  static VALUE
392
- pointer_id(VALUE self)
807
+ rb_xml_node_pointer_id(VALUE self)
393
808
  {
394
809
  xmlNodePtr node;
395
- Data_Get_Struct(self, xmlNode, node);
810
+ Noko_Node_Get_Struct(self, xmlNode, node);
396
811
 
397
812
  return INT2NUM((long)(node));
398
813
  }
399
814
 
400
815
  /*
401
- * call-seq:
402
- * encode_special_chars(string)
816
+ * :call-seq: encode_special_chars(string) → String
403
817
  *
404
818
  * Encode any special characters in +string+
405
819
  */
@@ -410,7 +824,7 @@ encode_special_chars(VALUE self, VALUE string)
410
824
  xmlChar *encoded;
411
825
  VALUE encoded_str;
412
826
 
413
- Data_Get_Struct(self, xmlNode, node);
827
+ Noko_Node_Get_Struct(self, xmlNode, node);
414
828
  encoded = xmlEncodeSpecialChars(
415
829
  node->doc,
416
830
  (const xmlChar *)StringValueCStr(string)
@@ -423,8 +837,8 @@ encode_special_chars(VALUE self, VALUE string)
423
837
  }
424
838
 
425
839
  /*
426
- * call-seq:
427
- * create_internal_subset(name, external_id, system_id)
840
+ * :call-seq:
841
+ * create_internal_subset(name, external_id, system_id)
428
842
  *
429
843
  * Create the internal subset of a document.
430
844
  *
@@ -441,7 +855,7 @@ create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
441
855
  xmlDocPtr doc;
442
856
  xmlDtdPtr dtd;
443
857
 
444
- Data_Get_Struct(self, xmlNode, node);
858
+ Noko_Node_Get_Struct(self, xmlNode, node);
445
859
 
446
860
  doc = node->doc;
447
861
 
@@ -462,8 +876,8 @@ create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
462
876
  }
463
877
 
464
878
  /*
465
- * call-seq:
466
- * create_external_subset(name, external_id, system_id)
879
+ * :call-seq:
880
+ * create_external_subset(name, external_id, system_id)
467
881
  *
468
882
  * Create an external subset
469
883
  */
@@ -474,7 +888,7 @@ create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
474
888
  xmlDocPtr doc;
475
889
  xmlDtdPtr dtd;
476
890
 
477
- Data_Get_Struct(self, xmlNode, node);
891
+ Noko_Node_Get_Struct(self, xmlNode, node);
478
892
 
479
893
  doc = node->doc;
480
894
 
@@ -495,8 +909,8 @@ create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
495
909
  }
496
910
 
497
911
  /*
498
- * call-seq:
499
- * external_subset
912
+ * :call-seq:
913
+ * external_subset()
500
914
  *
501
915
  * Get the external subset
502
916
  */
@@ -507,7 +921,7 @@ external_subset(VALUE self)
507
921
  xmlDocPtr doc;
508
922
  xmlDtdPtr dtd;
509
923
 
510
- Data_Get_Struct(self, xmlNode, node);
924
+ Noko_Node_Get_Struct(self, xmlNode, node);
511
925
 
512
926
  if (!node->doc) { return Qnil; }
513
927
 
@@ -520,8 +934,8 @@ external_subset(VALUE self)
520
934
  }
521
935
 
522
936
  /*
523
- * call-seq:
524
- * internal_subset
937
+ * :call-seq:
938
+ * internal_subset()
525
939
  *
526
940
  * Get the internal subset
527
941
  */
@@ -532,7 +946,7 @@ internal_subset(VALUE self)
532
946
  xmlDocPtr doc;
533
947
  xmlDtdPtr dtd;
534
948
 
535
- Data_Get_Struct(self, xmlNode, node);
949
+ Noko_Node_Get_Struct(self, xmlNode, node);
536
950
 
537
951
  if (!node->doc) { return Qnil; }
538
952
 
@@ -545,16 +959,19 @@ internal_subset(VALUE self)
545
959
  }
546
960
 
547
961
  /*
548
- * call-seq:
549
- * dup
550
- * dup(depth)
551
- * dup(depth, new_parent_doc)
962
+ * :call-seq:
963
+ * dup → Nokogiri::XML::Node
964
+ * dup(depth) → Nokogiri::XML::Node
965
+ * dup(depth, new_parent_doc) → Nokogiri::XML::Node
552
966
  *
553
967
  * Copy this node.
554
- * An optional depth may be passed in. 0 is a shallow copy, 1 (the default) is a deep copy.
555
- * An optional new_parent_doc may also be passed in, which will be the new
556
- * node's parent document. Defaults to the current node's document.
557
- * current document.
968
+ *
969
+ * [Parameters]
970
+ * - +depth+ 0 is a shallow copy, 1 (the default) is a deep copy.
971
+ * - +new_parent_doc+
972
+ * The new node's parent Document. Defaults to the this node's document.
973
+ *
974
+ * [Returns] The new Nokgiri::XML::Node
558
975
  */
559
976
  static VALUE
560
977
  duplicate_node(int argc, VALUE *argv, VALUE self)
@@ -565,7 +982,7 @@ duplicate_node(int argc, VALUE *argv, VALUE self)
565
982
  xmlDocPtr new_parent_doc;
566
983
  xmlNodePtr node, dup;
567
984
 
568
- Data_Get_Struct(self, xmlNode, node);
985
+ Noko_Node_Get_Struct(self, xmlNode, node);
569
986
 
570
987
  n_args = rb_scan_args(argc, argv, "02", &r_level, &r_new_parent_doc);
571
988
 
@@ -589,8 +1006,8 @@ duplicate_node(int argc, VALUE *argv, VALUE self)
589
1006
  }
590
1007
 
591
1008
  /*
592
- * call-seq:
593
- * unlink
1009
+ * :call-seq:
1010
+ * unlink() → self
594
1011
  *
595
1012
  * Unlink this node from its current context.
596
1013
  */
@@ -598,25 +1015,12 @@ static VALUE
598
1015
  unlink_node(VALUE self)
599
1016
  {
600
1017
  xmlNodePtr node;
601
- Data_Get_Struct(self, xmlNode, node);
1018
+ Noko_Node_Get_Struct(self, xmlNode, node);
602
1019
  xmlUnlinkNode(node);
603
1020
  noko_xml_document_pin_node(node);
604
1021
  return self;
605
1022
  }
606
1023
 
607
- /*
608
- * call-seq:
609
- * blank?
610
- *
611
- * Is this node blank?
612
- */
613
- static VALUE
614
- blank_eh(VALUE self)
615
- {
616
- xmlNodePtr node;
617
- Data_Get_Struct(self, xmlNode, node);
618
- return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
619
- }
620
1024
 
621
1025
  /*
622
1026
  * call-seq:
@@ -628,7 +1032,7 @@ static VALUE
628
1032
  next_sibling(VALUE self)
629
1033
  {
630
1034
  xmlNodePtr node, sibling;
631
- Data_Get_Struct(self, xmlNode, node);
1035
+ Noko_Node_Get_Struct(self, xmlNode, node);
632
1036
 
633
1037
  sibling = node->next;
634
1038
  if (!sibling) { return Qnil; }
@@ -646,7 +1050,7 @@ static VALUE
646
1050
  previous_sibling(VALUE self)
647
1051
  {
648
1052
  xmlNodePtr node, sibling;
649
- Data_Get_Struct(self, xmlNode, node);
1053
+ Noko_Node_Get_Struct(self, xmlNode, node);
650
1054
 
651
1055
  sibling = node->prev;
652
1056
  if (!sibling) { return Qnil; }
@@ -664,7 +1068,7 @@ static VALUE
664
1068
  next_element(VALUE self)
665
1069
  {
666
1070
  xmlNodePtr node, sibling;
667
- Data_Get_Struct(self, xmlNode, node);
1071
+ Noko_Node_Get_Struct(self, xmlNode, node);
668
1072
 
669
1073
  sibling = xmlNextElementSibling(node);
670
1074
  if (!sibling) { return Qnil; }
@@ -682,7 +1086,7 @@ static VALUE
682
1086
  previous_element(VALUE self)
683
1087
  {
684
1088
  xmlNodePtr node, sibling;
685
- Data_Get_Struct(self, xmlNode, node);
1089
+ Noko_Node_Get_Struct(self, xmlNode, node);
686
1090
 
687
1091
  /*
688
1092
  * note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
@@ -704,60 +1108,34 @@ replace(VALUE self, VALUE new_node)
704
1108
  VALUE reparent = reparent_node_with(self, new_node, xmlReplaceNodeWrapper);
705
1109
 
706
1110
  xmlNodePtr pivot;
707
- Data_Get_Struct(self, xmlNode, pivot);
1111
+ Noko_Node_Get_Struct(self, xmlNode, pivot);
708
1112
  noko_xml_document_pin_node(pivot);
709
1113
 
710
1114
  return reparent;
711
1115
  }
712
1116
 
713
1117
  /*
714
- * call-seq:
715
- * children
1118
+ * :call-seq:
1119
+ * element_children() → NodeSet
1120
+ * elements() → NodeSet
716
1121
  *
717
- * Get the list of children for this node as a NodeSet
718
- */
719
- static VALUE
720
- children(VALUE self)
721
- {
722
- xmlNodePtr node;
723
- xmlNodePtr child;
724
- xmlNodeSetPtr set;
725
- VALUE document;
726
- VALUE node_set;
727
-
728
- Data_Get_Struct(self, xmlNode, node);
729
-
730
- child = node->children;
731
- set = xmlXPathNodeSetCreate(child);
732
-
733
- document = DOC_RUBY_OBJECT(node->doc);
734
-
735
- if (!child) { return noko_xml_node_set_wrap(set, document); }
736
-
737
- child = child->next;
738
- while (NULL != child) {
739
- xmlXPathNodeSetAddUnique(set, child);
740
- child = child->next;
741
- }
742
-
743
- node_set = noko_xml_node_set_wrap(set, document);
744
-
745
- return node_set;
746
- }
747
-
748
- /*
749
- * call-seq:
750
- * element_children
1122
+ * [Returns]
1123
+ * The node's child elements as a NodeSet. Only children that are elements will be returned, which
1124
+ * notably excludes Text nodes.
751
1125
  *
752
- * Get the list of children for this node as a NodeSet. All nodes will be
753
- * element nodes.
1126
+ * *Example:*
754
1127
  *
755
- * Example:
1128
+ * Note that #children returns the Text node "hello" while #element_children does not.
756
1129
  *
757
- * @doc.root.element_children.all? { |x| x.element? } # => true
1130
+ * div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
1131
+ * div.element_children
1132
+ * # => [#<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]
1133
+ * div.children
1134
+ * # => [#<Nokogiri::XML::Text:0x64 "hello">,
1135
+ * # #<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]
758
1136
  */
759
1137
  static VALUE
760
- element_children(VALUE self)
1138
+ rb_xml_node_element_children(VALUE self)
761
1139
  {
762
1140
  xmlNodePtr node;
763
1141
  xmlNodePtr child;
@@ -765,7 +1143,7 @@ element_children(VALUE self)
765
1143
  VALUE document;
766
1144
  VALUE node_set;
767
1145
 
768
- Data_Get_Struct(self, xmlNode, node);
1146
+ Noko_Node_Get_Struct(self, xmlNode, node);
769
1147
 
770
1148
  child = xmlFirstElementChild(node);
771
1149
  set = xmlXPathNodeSetCreate(child);
@@ -786,38 +1164,25 @@ element_children(VALUE self)
786
1164
  }
787
1165
 
788
1166
  /*
789
- * call-seq:
790
- * child
1167
+ * :call-seq:
1168
+ * first_element_child() → Node
791
1169
  *
792
- * Returns the child node
793
- */
794
- static VALUE
795
- child(VALUE self)
796
- {
797
- xmlNodePtr node, child;
798
- Data_Get_Struct(self, xmlNode, node);
799
-
800
- child = node->children;
801
- if (!child) { return Qnil; }
802
-
803
- return noko_xml_node_wrap(Qnil, child);
804
- }
805
-
806
- /*
807
- * call-seq:
808
- * first_element_child
1170
+ * [Returns] The first child Node that is an element.
809
1171
  *
810
- * Returns the first child node of this node that is an element.
1172
+ * *Example:*
811
1173
  *
812
- * Example:
1174
+ * Note that the "hello" child, which is a Text node, is skipped and the <tt><span></tt> element is
1175
+ * returned.
813
1176
  *
814
- * @doc.root.first_element_child.element? # => true
1177
+ * div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
1178
+ * div.first_element_child
1179
+ * # => #(Element:0x3c { name = "span", children = [ #(Text "world")] })
815
1180
  */
816
1181
  static VALUE
817
- first_element_child(VALUE self)
1182
+ rb_xml_node_first_element_child(VALUE self)
818
1183
  {
819
1184
  xmlNodePtr node, child;
820
- Data_Get_Struct(self, xmlNode, node);
1185
+ Noko_Node_Get_Struct(self, xmlNode, node);
821
1186
 
822
1187
  child = xmlFirstElementChild(node);
823
1188
  if (!child) { return Qnil; }
@@ -826,20 +1191,25 @@ first_element_child(VALUE self)
826
1191
  }
827
1192
 
828
1193
  /*
829
- * call-seq:
830
- * last_element_child
1194
+ * :call-seq:
1195
+ * last_element_child() → Node
1196
+ *
1197
+ * [Returns] The last child Node that is an element.
831
1198
  *
832
- * Returns the last child node of this node that is an element.
1199
+ * *Example:*
833
1200
  *
834
- * Example:
1201
+ * Note that the "hello" child, which is a Text node, is skipped and the <tt><span>yes</span></tt>
1202
+ * element is returned.
835
1203
  *
836
- * @doc.root.last_element_child.element? # => true
1204
+ * div = Nokogiri::HTML5("<div><span>no</span><span>yes</span>skip</div>").at_css("div")
1205
+ * div.last_element_child
1206
+ * # => #(Element:0x3c { name = "span", children = [ #(Text "yes")] })
837
1207
  */
838
1208
  static VALUE
839
- last_element_child(VALUE self)
1209
+ rb_xml_node_last_element_child(VALUE self)
840
1210
  {
841
1211
  xmlNodePtr node, child;
842
- Data_Get_Struct(self, xmlNode, node);
1212
+ Noko_Node_Get_Struct(self, xmlNode, node);
843
1213
 
844
1214
  child = xmlLastElementChild(node);
845
1215
  if (!child) { return Qnil; }
@@ -857,7 +1227,7 @@ static VALUE
857
1227
  key_eh(VALUE self, VALUE attribute)
858
1228
  {
859
1229
  xmlNodePtr node;
860
- Data_Get_Struct(self, xmlNode, node);
1230
+ Noko_Node_Get_Struct(self, xmlNode, node);
861
1231
  if (xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
862
1232
  return Qtrue;
863
1233
  }
@@ -874,7 +1244,7 @@ static VALUE
874
1244
  namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
875
1245
  {
876
1246
  xmlNodePtr node;
877
- Data_Get_Struct(self, xmlNode, node);
1247
+ Noko_Node_Get_Struct(self, xmlNode, node);
878
1248
  if (xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
879
1249
  NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace))) {
880
1250
  return Qtrue;
@@ -893,7 +1263,7 @@ set(VALUE self, VALUE property, VALUE value)
893
1263
  {
894
1264
  xmlNodePtr node, cur;
895
1265
  xmlAttrPtr prop;
896
- Data_Get_Struct(self, xmlNode, node);
1266
+ Noko_Node_Get_Struct(self, xmlNode, node);
897
1267
 
898
1268
  /* If a matching attribute node already exists, then xmlSetProp will destroy
899
1269
  * the existing node's children. However, if Nokogiri has a node object
@@ -938,7 +1308,7 @@ get(VALUE self, VALUE rattribute)
938
1308
 
939
1309
  if (NIL_P(rattribute)) { return Qnil; }
940
1310
 
941
- Data_Get_Struct(self, xmlNode, node);
1311
+ Noko_Node_Get_Struct(self, xmlNode, node);
942
1312
  attribute = xmlCharStrdup(StringValueCStr(rattribute));
943
1313
 
944
1314
  colon = DISCARD_CONST_QUAL_XMLCHAR(xmlStrchr(attribute, (const xmlChar)':'));
@@ -980,10 +1350,10 @@ set_namespace(VALUE self, VALUE namespace)
980
1350
  xmlNodePtr node;
981
1351
  xmlNsPtr ns = NULL;
982
1352
 
983
- Data_Get_Struct(self, xmlNode, node);
1353
+ Noko_Node_Get_Struct(self, xmlNode, node);
984
1354
 
985
1355
  if (!NIL_P(namespace)) {
986
- Data_Get_Struct(namespace, xmlNs, ns);
1356
+ Noko_Namespace_Get_Struct(namespace, xmlNs, ns);
987
1357
  }
988
1358
 
989
1359
  xmlSetNs(node, ns);
@@ -992,70 +1362,32 @@ set_namespace(VALUE self, VALUE namespace)
992
1362
  }
993
1363
 
994
1364
  /*
995
- * call-seq:
996
- * attribute(name)
1365
+ * :call-seq:
1366
+ * namespace() → Namespace
997
1367
  *
998
- * Get the attribute node with +name+
999
- */
1000
- static VALUE
1001
- attr(VALUE self, VALUE name)
1002
- {
1003
- xmlNodePtr node;
1004
- xmlAttrPtr prop;
1005
- Data_Get_Struct(self, xmlNode, node);
1006
- prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
1007
-
1008
- if (! prop) { return Qnil; }
1009
- return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
1010
- }
1011
-
1012
- /*
1013
- * call-seq:
1014
- * attribute_with_ns(name, namespace)
1368
+ * [Returns] The Namespace of the element or attribute node, or +nil+ if there is no namespace.
1015
1369
  *
1016
- * Get the attribute node with +name+ and +namespace+
1017
- */
1018
- static VALUE
1019
- attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
1020
- {
1021
- xmlNodePtr node;
1022
- xmlAttrPtr prop;
1023
- Data_Get_Struct(self, xmlNode, node);
1024
- prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
1025
- NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
1026
-
1027
- if (! prop) { return Qnil; }
1028
- return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
1029
- }
1030
-
1031
- /*
1032
- * @overload attribute_nodes()
1033
- * Get the attributes for a Node
1034
- * @return [Array<Nokogiri::XML::Attr>] containing the Node's attributes.
1035
- */
1036
- static VALUE
1037
- attribute_nodes(VALUE rb_node)
1038
- {
1039
- xmlNodePtr c_node;
1040
-
1041
- Data_Get_Struct(rb_node, xmlNode, c_node);
1042
-
1043
- return noko_xml_node_attrs(c_node);
1044
- }
1045
-
1046
-
1047
- /*
1048
- * call-seq:
1049
- * namespace()
1370
+ * *Example:*
1050
1371
  *
1051
- * returns the namespace of the element or attribute node as a Namespace
1052
- * object, or nil if there is no namespace for the element or attribute.
1372
+ * doc = Nokogiri::XML(<<~EOF)
1373
+ * <root>
1374
+ * <first/>
1375
+ * <second xmlns="http://example.com/child"/>
1376
+ * <foo:third xmlns:foo="http://example.com/foo"/>
1377
+ * </root>
1378
+ * EOF
1379
+ * doc.at_xpath("//first").namespace
1380
+ * # => nil
1381
+ * doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace
1382
+ * # => #(Namespace:0x3c { href = "http://example.com/child" })
1383
+ * doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace
1384
+ * # => #(Namespace:0x50 { prefix = "foo", href = "http://example.com/foo" })
1053
1385
  */
1054
1386
  static VALUE
1055
- noko_xml_node_namespace(VALUE rb_node)
1387
+ rb_xml_node_namespace(VALUE rb_node)
1056
1388
  {
1057
1389
  xmlNodePtr c_node ;
1058
- Data_Get_Struct(rb_node, xmlNode, c_node);
1390
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1059
1391
 
1060
1392
  if (c_node->ns) {
1061
1393
  return noko_xml_namespace_wrap(c_node->ns, c_node->doc);
@@ -1065,10 +1397,32 @@ noko_xml_node_namespace(VALUE rb_node)
1065
1397
  }
1066
1398
 
1067
1399
  /*
1068
- * call-seq:
1069
- * namespace_definitions()
1400
+ * :call-seq:
1401
+ * namespace_definitions() → Array<Nokogiri::XML::Namespace>
1402
+ *
1403
+ * [Returns]
1404
+ * Namespaces that are defined directly on this node, as an Array of Namespace objects. The array
1405
+ * will be empty if no namespaces are defined on this node.
1406
+ *
1407
+ * *Example:*
1070
1408
  *
1071
- * returns namespaces defined on self element directly, as an array of Namespace objects. Includes both a default namespace (as in"xmlns="), and prefixed namespaces (as in "xmlns:prefix=").
1409
+ * doc = Nokogiri::XML(<<~EOF)
1410
+ * <root xmlns="http://example.com/root">
1411
+ * <first/>
1412
+ * <second xmlns="http://example.com/child" xmlns:unused="http://example.com/unused"/>
1413
+ * <foo:third xmlns:foo="http://example.com/foo"/>
1414
+ * </root>
1415
+ * EOF
1416
+ * doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_definitions
1417
+ * # => []
1418
+ * doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace_definitions
1419
+ * # => [#(Namespace:0x3c { href = "http://example.com/child" }),
1420
+ * # #(Namespace:0x50 {
1421
+ * # prefix = "unused",
1422
+ * # href = "http://example.com/unused"
1423
+ * # })]
1424
+ * doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace_definitions
1425
+ * # => [#(Namespace:0x64 { prefix = "foo", href = "http://example.com/foo" })]
1072
1426
  */
1073
1427
  static VALUE
1074
1428
  namespace_definitions(VALUE rb_node)
@@ -1078,7 +1432,7 @@ namespace_definitions(VALUE rb_node)
1078
1432
  xmlNsPtr c_namespace;
1079
1433
  VALUE definitions = rb_ary_new();
1080
1434
 
1081
- Data_Get_Struct(rb_node, xmlNode, c_node);
1435
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1082
1436
 
1083
1437
  c_namespace = c_node->nsDef;
1084
1438
  if (!c_namespace) {
@@ -1094,23 +1448,42 @@ namespace_definitions(VALUE rb_node)
1094
1448
  }
1095
1449
 
1096
1450
  /*
1097
- * call-seq:
1098
- * namespace_scopes()
1451
+ * :call-seq:
1452
+ * namespace_scopes() → Array<Nokogiri::XML::Namespace>
1099
1453
  *
1100
- * returns namespaces in scope for self -- those defined on self element
1101
- * directly or any ancestor node -- as an array of Namespace objects. Default
1102
- * namespaces ("xmlns=" style) for self are included in this array; Default
1103
- * namespaces for ancestors, however, are not. See also #namespaces
1454
+ * [Returns] Array of all the Namespaces on this node and its ancestors.
1455
+ *
1456
+ * See also #namespaces
1457
+ *
1458
+ * *Example:*
1459
+ *
1460
+ * doc = Nokogiri::XML(<<~EOF)
1461
+ * <root xmlns="http://example.com/root" xmlns:bar="http://example.com/bar">
1462
+ * <first/>
1463
+ * <second xmlns="http://example.com/child"/>
1464
+ * <third xmlns:foo="http://example.com/foo"/>
1465
+ * </root>
1466
+ * EOF
1467
+ * doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_scopes
1468
+ * # => [#(Namespace:0x3c { href = "http://example.com/root" }),
1469
+ * # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
1470
+ * doc.at_xpath("//child:second", "child" => "http://example.com/child").namespace_scopes
1471
+ * # => [#(Namespace:0x64 { href = "http://example.com/child" }),
1472
+ * # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
1473
+ * doc.at_xpath("//root:third", "root" => "http://example.com/root").namespace_scopes
1474
+ * # => [#(Namespace:0x78 { prefix = "foo", href = "http://example.com/foo" }),
1475
+ * # #(Namespace:0x3c { href = "http://example.com/root" }),
1476
+ * # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
1104
1477
  */
1105
1478
  static VALUE
1106
- namespace_scopes(VALUE rb_node)
1479
+ rb_xml_node_namespace_scopes(VALUE rb_node)
1107
1480
  {
1108
1481
  xmlNodePtr c_node ;
1109
1482
  xmlNsPtr *namespaces;
1110
1483
  VALUE scopes = rb_ary_new();
1111
1484
  int j;
1112
1485
 
1113
- Data_Get_Struct(rb_node, xmlNode, c_node);
1486
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1114
1487
 
1115
1488
  namespaces = xmlGetNsList(c_node->doc, c_node);
1116
1489
  if (!namespaces) {
@@ -1135,7 +1508,7 @@ static VALUE
1135
1508
  node_type(VALUE self)
1136
1509
  {
1137
1510
  xmlNodePtr node;
1138
- Data_Get_Struct(self, xmlNode, node);
1511
+ Noko_Node_Get_Struct(self, xmlNode, node);
1139
1512
  return INT2NUM((long)node->type);
1140
1513
  }
1141
1514
 
@@ -1149,7 +1522,7 @@ static VALUE
1149
1522
  set_native_content(VALUE self, VALUE content)
1150
1523
  {
1151
1524
  xmlNodePtr node, child, next ;
1152
- Data_Get_Struct(self, xmlNode, node);
1525
+ Noko_Node_Get_Struct(self, xmlNode, node);
1153
1526
 
1154
1527
  child = node->children;
1155
1528
  while (NULL != child) {
@@ -1163,30 +1536,6 @@ set_native_content(VALUE self, VALUE content)
1163
1536
  return content;
1164
1537
  }
1165
1538
 
1166
- /*
1167
- * call-seq:
1168
- * content
1169
- *
1170
- * Returns the plaintext content for this Node. Note that entities will always
1171
- * be expanded in the returned string.
1172
- */
1173
- static VALUE
1174
- get_native_content(VALUE self)
1175
- {
1176
- xmlNodePtr node;
1177
- xmlChar *content;
1178
-
1179
- Data_Get_Struct(self, xmlNode, node);
1180
-
1181
- content = xmlNodeGetContent(node);
1182
- if (content) {
1183
- VALUE rval = NOKOGIRI_STR_NEW2(content);
1184
- xmlFree(content);
1185
- return rval;
1186
- }
1187
- return Qnil;
1188
- }
1189
-
1190
1539
  /*
1191
1540
  * call-seq:
1192
1541
  * lang=
@@ -1199,7 +1548,7 @@ set_lang(VALUE self_rb, VALUE lang_rb)
1199
1548
  xmlNodePtr self ;
1200
1549
  xmlChar *lang ;
1201
1550
 
1202
- Data_Get_Struct(self_rb, xmlNode, self);
1551
+ Noko_Node_Get_Struct(self_rb, xmlNode, self);
1203
1552
  lang = (xmlChar *)StringValueCStr(lang_rb);
1204
1553
 
1205
1554
  xmlNodeSetLang(self, lang);
@@ -1221,7 +1570,7 @@ get_lang(VALUE self_rb)
1221
1570
  xmlChar *lang ;
1222
1571
  VALUE lang_rb ;
1223
1572
 
1224
- Data_Get_Struct(self_rb, xmlNode, self);
1573
+ Noko_Node_Get_Struct(self_rb, xmlNode, self);
1225
1574
 
1226
1575
  lang = xmlNodeGetLang(self);
1227
1576
  if (lang) {
@@ -1250,7 +1599,7 @@ static VALUE
1250
1599
  get_parent(VALUE self)
1251
1600
  {
1252
1601
  xmlNodePtr node, parent;
1253
- Data_Get_Struct(self, xmlNode, node);
1602
+ Noko_Node_Get_Struct(self, xmlNode, node);
1254
1603
 
1255
1604
  parent = node->parent;
1256
1605
  if (!parent) { return Qnil; }
@@ -1268,7 +1617,7 @@ static VALUE
1268
1617
  set_name(VALUE self, VALUE new_name)
1269
1618
  {
1270
1619
  xmlNodePtr node;
1271
- Data_Get_Struct(self, xmlNode, node);
1620
+ Noko_Node_Get_Struct(self, xmlNode, node);
1272
1621
  xmlNodeSetName(node, (xmlChar *)StringValueCStr(new_name));
1273
1622
  return new_name;
1274
1623
  }
@@ -1283,7 +1632,7 @@ static VALUE
1283
1632
  get_name(VALUE self)
1284
1633
  {
1285
1634
  xmlNodePtr node;
1286
- Data_Get_Struct(self, xmlNode, node);
1635
+ Noko_Node_Get_Struct(self, xmlNode, node);
1287
1636
  if (node->name) {
1288
1637
  return NOKOGIRI_STR_NEW2(node->name);
1289
1638
  }
@@ -1297,13 +1646,13 @@ get_name(VALUE self)
1297
1646
  * Returns the path associated with this Node
1298
1647
  */
1299
1648
  static VALUE
1300
- noko_xml_node_path(VALUE rb_node)
1649
+ rb_xml_node_path(VALUE rb_node)
1301
1650
  {
1302
1651
  xmlNodePtr c_node;
1303
1652
  xmlChar *c_path ;
1304
1653
  VALUE rval;
1305
1654
 
1306
- Data_Get_Struct(rb_node, xmlNode, c_node);
1655
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1307
1656
 
1308
1657
  c_path = xmlGetNodePath(c_node);
1309
1658
  if (c_path == NULL) {
@@ -1352,7 +1701,7 @@ native_write_to(
1352
1701
  const char *before_indent;
1353
1702
  xmlSaveCtxtPtr savectx;
1354
1703
 
1355
- Data_Get_Struct(self, xmlNode, node);
1704
+ Noko_Node_Get_Struct(self, xmlNode, node);
1356
1705
 
1357
1706
  xmlIndentTreeOutput = 1;
1358
1707
 
@@ -1376,18 +1725,39 @@ native_write_to(
1376
1725
  }
1377
1726
 
1378
1727
  /*
1379
- * call-seq:
1380
- * line
1728
+ * :call-seq:
1729
+ * line() → Integer
1730
+ *
1731
+ * [Returns] The line number of this Node.
1732
+ *
1733
+ * ---
1734
+ *
1735
+ * <b> ⚠ The CRuby and JRuby implementations differ in important ways! </b>
1381
1736
  *
1382
- * Returns the line for this Node
1737
+ * Semantic differences:
1738
+ * - The CRuby method reflects the node's line number <i>in the parsed string</i>
1739
+ * - The JRuby method reflects the node's line number <i>in the final DOM structure</i> after
1740
+ * corrections have been applied
1741
+ *
1742
+ * Performance differences:
1743
+ * - The CRuby method is {O(1)}[https://en.wikipedia.org/wiki/Time_complexity#Constant_time]
1744
+ * (constant time)
1745
+ * - The JRuby method is {O(n)}[https://en.wikipedia.org/wiki/Time_complexity#Linear_time] (linear
1746
+ * time, where n is the number of nodes before/above the element in the DOM)
1747
+ *
1748
+ * If you'd like to help improve the JRuby implementation, please review these issues and reach out
1749
+ * to the maintainers:
1750
+ * - https://github.com/sparklemotion/nokogiri/issues/1223
1751
+ * - https://github.com/sparklemotion/nokogiri/pull/2177
1752
+ * - https://github.com/sparklemotion/nokogiri/issues/2380
1383
1753
  */
1384
1754
  static VALUE
1385
- line(VALUE self)
1755
+ rb_xml_node_line(VALUE rb_node)
1386
1756
  {
1387
- xmlNodePtr node;
1388
- Data_Get_Struct(self, xmlNode, node);
1757
+ xmlNodePtr c_node;
1758
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1389
1759
 
1390
- return INT2NUM(xmlGetLineNo(node));
1760
+ return INT2NUM(xmlGetLineNo(c_node));
1391
1761
  }
1392
1762
 
1393
1763
  /*
@@ -1397,90 +1767,56 @@ line(VALUE self)
1397
1767
  * Sets the line for this Node. num must be less than 65535.
1398
1768
  */
1399
1769
  static VALUE
1400
- set_line(VALUE self, VALUE num)
1770
+ rb_xml_node_line_set(VALUE rb_node, VALUE rb_line_number)
1401
1771
  {
1402
- xmlNodePtr node;
1403
- int value = NUM2INT(num);
1404
-
1405
- Data_Get_Struct(self, xmlNode, node);
1406
- if (value < 65535) {
1407
- node->line = value;
1408
- }
1409
-
1410
- return num;
1411
- }
1412
-
1413
- /*
1414
- * call-seq:
1415
- * add_namespace_definition(prefix, href)
1416
- *
1417
- * Adds a namespace definition with +prefix+ using +href+ value. The result is
1418
- * as if parsed XML for this node had included an attribute
1419
- * 'xmlns:prefix=value'. A default namespace for this node ("xmlns=") can be
1420
- * added by passing 'nil' for prefix. Namespaces added this way will not
1421
- * show up in #attributes, but they will be included as an xmlns attribute
1422
- * when the node is serialized to XML.
1423
- */
1424
- static VALUE
1425
- add_namespace_definition(VALUE rb_node, VALUE rb_prefix, VALUE rb_href)
1426
- {
1427
- xmlNodePtr c_node, element;
1428
- xmlNsPtr c_namespace;
1429
- const xmlChar *c_prefix = (const xmlChar *)(NIL_P(rb_prefix) ? NULL : StringValueCStr(rb_prefix));
1772
+ xmlNodePtr c_node;
1773
+ int line_number = NUM2INT(rb_line_number);
1430
1774
 
1431
- Data_Get_Struct(rb_node, xmlNode, c_node);
1432
- element = c_node ;
1775
+ Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
1433
1776
 
1434
- c_namespace = xmlSearchNs(c_node->doc, c_node, c_prefix);
1435
-
1436
- if (!c_namespace) {
1437
- if (c_node->type != XML_ELEMENT_NODE) {
1438
- element = c_node->parent;
1777
+ // libxml2 optionally uses xmlNode.psvi to store longer line numbers, but only for text nodes.
1778
+ // search for "psvi" in SAX2.c and tree.c to learn more.
1779
+ if (line_number < 65535) {
1780
+ c_node->line = (short) line_number;
1781
+ } else {
1782
+ c_node->line = 65535;
1783
+ if (c_node->type == XML_TEXT_NODE) {
1784
+ c_node->psvi = (void *)(ptrdiff_t) line_number;
1439
1785
  }
1440
- c_namespace = xmlNewNs(element, (const xmlChar *)StringValueCStr(rb_href), c_prefix);
1441
- }
1442
-
1443
- if (!c_namespace) {
1444
- return Qnil ;
1445
1786
  }
1446
1787
 
1447
- if (NIL_P(rb_prefix) || c_node != element) {
1448
- xmlSetNs(c_node, c_namespace);
1449
- }
1450
-
1451
- return noko_xml_namespace_wrap(c_namespace, c_node->doc);
1788
+ return rb_line_number;
1452
1789
  }
1453
1790
 
1454
- /*
1455
- * @overload new(name, document)
1456
- * Create a new node with +name+ sharing GC lifecycle with +document+.
1457
- * @param name [String]
1458
- * @param document [Nokogiri::XML::Document]
1459
- * @yieldparam node [Nokogiri::XML::Node]
1460
- * @return [Nokogiri::XML::Node]
1461
- * @see Nokogiri::XML::Node#initialize
1462
- */
1791
+ /* :nodoc: documented in lib/nokogiri/xml/node.rb */
1463
1792
  static VALUE
1464
1793
  rb_xml_node_new(int argc, VALUE *argv, VALUE klass)
1465
1794
  {
1466
- xmlDocPtr doc;
1467
- xmlNodePtr node;
1468
- VALUE name;
1469
- VALUE document;
1795
+ xmlNodePtr c_document_node;
1796
+ xmlNodePtr c_node;
1797
+ VALUE rb_name;
1798
+ VALUE rb_document_node;
1470
1799
  VALUE rest;
1471
1800
  VALUE rb_node;
1472
1801
 
1473
- rb_scan_args(argc, argv, "2*", &name, &document, &rest);
1802
+ rb_scan_args(argc, argv, "2*", &rb_name, &rb_document_node, &rest);
1474
1803
 
1475
- Data_Get_Struct(document, xmlDoc, doc);
1804
+ if (!rb_obj_is_kind_of(rb_document_node, cNokogiriXmlNode)) {
1805
+ rb_raise(rb_eArgError, "document must be a Nokogiri::XML::Node");
1806
+ }
1807
+ if (!rb_obj_is_kind_of(rb_document_node, cNokogiriXmlDocument)) {
1808
+ // TODO: deprecate allowing Node
1809
+ NOKO_WARN_DEPRECATION("Passing a Node as the second parameter to Node.new is deprecated. Please pass a Document instead, or prefer an alternative constructor like Node#add_child. This will become an error in a future release of Nokogiri.");
1810
+ }
1811
+ Noko_Node_Get_Struct(rb_document_node, xmlNode, c_document_node);
1476
1812
 
1477
- node = xmlNewNode(NULL, (xmlChar *)StringValueCStr(name));
1478
- node->doc = doc->doc;
1479
- noko_xml_document_pin_node(node);
1813
+ c_node = xmlNewNode(NULL, (xmlChar *)StringValueCStr(rb_name));
1814
+ c_node->doc = c_document_node->doc;
1815
+ noko_xml_document_pin_node(c_node);
1480
1816
 
1481
1817
  rb_node = noko_xml_node_wrap(
1482
1818
  klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
1483
- node
1819
+ c_node
1484
1820
  );
1485
1821
  rb_obj_call_init(rb_node, argc, argv);
1486
1822
 
@@ -1502,7 +1838,7 @@ dump_html(VALUE self)
1502
1838
  xmlNodePtr node ;
1503
1839
  VALUE html;
1504
1840
 
1505
- Data_Get_Struct(self, xmlNode, node);
1841
+ Noko_Node_Get_Struct(self, xmlNode, node);
1506
1842
 
1507
1843
  buf = xmlBufferCreate() ;
1508
1844
  htmlNodeDump(buf, node->doc, node);
@@ -1521,8 +1857,8 @@ static VALUE
1521
1857
  compare(VALUE self, VALUE _other)
1522
1858
  {
1523
1859
  xmlNodePtr node, other;
1524
- Data_Get_Struct(self, xmlNode, node);
1525
- Data_Get_Struct(_other, xmlNode, other);
1860
+ Noko_Node_Get_Struct(self, xmlNode, node);
1861
+ Noko_Node_Get_Struct(_other, xmlNode, other);
1526
1862
 
1527
1863
  return INT2NUM((long)xmlXPathCmpNodes(other, node));
1528
1864
  }
@@ -1542,7 +1878,7 @@ process_xincludes(VALUE self, VALUE options)
1542
1878
  xmlNodePtr node;
1543
1879
  VALUE error_list = rb_ary_new();
1544
1880
 
1545
- Data_Get_Struct(self, xmlNode, node);
1881
+ Noko_Node_Get_Struct(self, xmlNode, node);
1546
1882
 
1547
1883
  xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher);
1548
1884
  rcode = xmlXIncludeProcessTreeFlags(node, (int)NUM2INT(options));
@@ -1573,7 +1909,7 @@ in_context(VALUE self, VALUE _str, VALUE _options)
1573
1909
  VALUE doc, err;
1574
1910
  int doc_is_empty;
1575
1911
 
1576
- Data_Get_Struct(self, xmlNode, node);
1912
+ Noko_Node_Get_Struct(self, xmlNode, node);
1577
1913
 
1578
1914
  doc = DOC_RUBY_OBJECT(node->doc);
1579
1915
  err = rb_iv_get(doc, "@errors");
@@ -1614,9 +1950,7 @@ in_context(VALUE self, VALUE _str, VALUE _options)
1614
1950
  */
1615
1951
  child_iter = node->doc->children ;
1616
1952
  while (child_iter) {
1617
- if (child_iter->parent != (xmlNodePtr)node->doc) {
1618
- child_iter->parent = (xmlNodePtr)node->doc;
1619
- }
1953
+ child_iter->parent = (xmlNodePtr)node->doc;
1620
1954
  child_iter = child_iter->next;
1621
1955
  }
1622
1956
 
@@ -1667,14 +2001,12 @@ in_context(VALUE self, VALUE _str, VALUE _options)
1667
2001
  return noko_xml_node_set_wrap(set, doc);
1668
2002
  }
1669
2003
 
1670
-
1671
2004
  VALUE
1672
2005
  noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
1673
2006
  {
1674
2007
  VALUE rb_document, rb_node_cache, rb_node;
1675
2008
  nokogiriTuplePtr node_has_a_document;
1676
2009
  xmlDocPtr c_doc;
1677
- void (*mark_method)(xmlNodePtr) = NULL ;
1678
2010
 
1679
2011
  assert(c_node);
1680
2012
 
@@ -1682,11 +2014,9 @@ noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
1682
2014
  return DOC_RUBY_OBJECT(c_node->doc);
1683
2015
  }
1684
2016
 
1685
- /* It's OK if the node doesn't have a fully-realized document (as in XML::Reader). */
1686
- /* see https://github.com/sparklemotion/nokogiri/issues/95 */
1687
- /* and https://github.com/sparklemotion/nokogiri/issues/439 */
1688
2017
  c_doc = c_node->doc;
1689
- if (c_doc->type == XML_DOCUMENT_FRAG_NODE) { c_doc = c_doc->doc; }
2018
+
2019
+ // Nodes yielded from XML::Reader don't have a fully-realized Document
1690
2020
  node_has_a_document = DOC_RUBY_OBJECT_TEST(c_doc);
1691
2021
 
1692
2022
  if (c_node->_private && node_has_a_document) {
@@ -1736,9 +2066,7 @@ noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
1736
2066
  }
1737
2067
  }
1738
2068
 
1739
- mark_method = node_has_a_document ? mark : NULL ;
1740
-
1741
- rb_node = Data_Wrap_Struct(rb_class, mark_method, debug_node_dealloc, c_node) ;
2069
+ rb_node = TypedData_Wrap_Struct(rb_class, &nokogiri_node_type, c_node) ;
1742
2070
  c_node->_private = (void *)rb_node;
1743
2071
 
1744
2072
  if (node_has_a_document) {
@@ -1779,61 +2107,59 @@ noko_init_xml_node()
1779
2107
 
1780
2108
  rb_define_singleton_method(cNokogiriXmlNode, "new", rb_xml_node_new, -1);
1781
2109
 
1782
- rb_define_method(cNokogiriXmlNode, "add_namespace_definition", add_namespace_definition, 2);
2110
+ rb_define_method(cNokogiriXmlNode, "add_namespace_definition", rb_xml_node_add_namespace_definition, 2);
2111
+ rb_define_method(cNokogiriXmlNode, "attribute", rb_xml_node_attribute, 1);
2112
+ rb_define_method(cNokogiriXmlNode, "attribute_nodes", rb_xml_node_attribute_nodes, 0);
2113
+ rb_define_method(cNokogiriXmlNode, "attribute_with_ns", rb_xml_node_attribute_with_ns, 2);
2114
+ rb_define_method(cNokogiriXmlNode, "blank?", rb_xml_node_blank_eh, 0);
2115
+ rb_define_method(cNokogiriXmlNode, "child", rb_xml_node_child, 0);
2116
+ rb_define_method(cNokogiriXmlNode, "children", rb_xml_node_children, 0);
2117
+ rb_define_method(cNokogiriXmlNode, "content", rb_xml_node_content, 0);
2118
+ rb_define_method(cNokogiriXmlNode, "create_external_subset", create_external_subset, 3);
2119
+ rb_define_method(cNokogiriXmlNode, "create_internal_subset", create_internal_subset, 3);
2120
+ rb_define_method(cNokogiriXmlNode, "document", rb_xml_node_document, 0);
2121
+ rb_define_method(cNokogiriXmlNode, "dup", duplicate_node, -1);
2122
+ rb_define_method(cNokogiriXmlNode, "element_children", rb_xml_node_element_children, 0);
2123
+ rb_define_method(cNokogiriXmlNode, "encode_special_chars", encode_special_chars, 1);
2124
+ rb_define_method(cNokogiriXmlNode, "external_subset", external_subset, 0);
2125
+ rb_define_method(cNokogiriXmlNode, "first_element_child", rb_xml_node_first_element_child, 0);
2126
+ rb_define_method(cNokogiriXmlNode, "internal_subset", internal_subset, 0);
2127
+ rb_define_method(cNokogiriXmlNode, "key?", key_eh, 1);
2128
+ rb_define_method(cNokogiriXmlNode, "lang", get_lang, 0);
2129
+ rb_define_method(cNokogiriXmlNode, "lang=", set_lang, 1);
2130
+ rb_define_method(cNokogiriXmlNode, "last_element_child", rb_xml_node_last_element_child, 0);
2131
+ rb_define_method(cNokogiriXmlNode, "line", rb_xml_node_line, 0);
2132
+ rb_define_method(cNokogiriXmlNode, "line=", rb_xml_node_line_set, 1);
2133
+ rb_define_method(cNokogiriXmlNode, "namespace", rb_xml_node_namespace, 0);
2134
+ rb_define_method(cNokogiriXmlNode, "namespace_definitions", namespace_definitions, 0);
2135
+ rb_define_method(cNokogiriXmlNode, "namespace_scopes", rb_xml_node_namespace_scopes, 0);
2136
+ rb_define_method(cNokogiriXmlNode, "namespaced_key?", namespaced_key_eh, 2);
2137
+ rb_define_method(cNokogiriXmlNode, "native_content=", set_native_content, 1);
2138
+ rb_define_method(cNokogiriXmlNode, "next_element", next_element, 0);
2139
+ rb_define_method(cNokogiriXmlNode, "next_sibling", next_sibling, 0);
1783
2140
  rb_define_method(cNokogiriXmlNode, "node_name", get_name, 0);
1784
- rb_define_method(cNokogiriXmlNode, "document", document, 0);
1785
2141
  rb_define_method(cNokogiriXmlNode, "node_name=", set_name, 1);
2142
+ rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
1786
2143
  rb_define_method(cNokogiriXmlNode, "parent", get_parent, 0);
1787
- rb_define_method(cNokogiriXmlNode, "child", child, 0);
1788
- rb_define_method(cNokogiriXmlNode, "first_element_child", first_element_child, 0);
1789
- rb_define_method(cNokogiriXmlNode, "last_element_child", last_element_child, 0);
1790
- rb_define_method(cNokogiriXmlNode, "children", children, 0);
1791
- rb_define_method(cNokogiriXmlNode, "element_children", element_children, 0);
1792
- rb_define_method(cNokogiriXmlNode, "next_sibling", next_sibling, 0);
1793
- rb_define_method(cNokogiriXmlNode, "previous_sibling", previous_sibling, 0);
1794
- rb_define_method(cNokogiriXmlNode, "next_element", next_element, 0);
2144
+ rb_define_method(cNokogiriXmlNode, "path", rb_xml_node_path, 0);
2145
+ rb_define_method(cNokogiriXmlNode, "pointer_id", rb_xml_node_pointer_id, 0);
1795
2146
  rb_define_method(cNokogiriXmlNode, "previous_element", previous_element, 0);
1796
- rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
1797
- rb_define_method(cNokogiriXmlNode, "path", noko_xml_node_path, 0);
1798
- rb_define_method(cNokogiriXmlNode, "key?", key_eh, 1);
1799
- rb_define_method(cNokogiriXmlNode, "namespaced_key?", namespaced_key_eh, 2);
1800
- rb_define_method(cNokogiriXmlNode, "blank?", blank_eh, 0);
1801
- rb_define_method(cNokogiriXmlNode, "attribute_nodes", attribute_nodes, 0);
1802
- rb_define_method(cNokogiriXmlNode, "attribute", attr, 1);
1803
- rb_define_method(cNokogiriXmlNode, "attribute_with_ns", attribute_with_ns, 2);
1804
- rb_define_method(cNokogiriXmlNode, "namespace", noko_xml_node_namespace, 0);
1805
- rb_define_method(cNokogiriXmlNode, "namespace_definitions", namespace_definitions, 0);
1806
- rb_define_method(cNokogiriXmlNode, "namespace_scopes", namespace_scopes, 0);
1807
- rb_define_method(cNokogiriXmlNode, "encode_special_chars", encode_special_chars, 1);
1808
- rb_define_method(cNokogiriXmlNode, "dup", duplicate_node, -1);
2147
+ rb_define_method(cNokogiriXmlNode, "previous_sibling", previous_sibling, 0);
1809
2148
  rb_define_method(cNokogiriXmlNode, "unlink", unlink_node, 0);
1810
- rb_define_method(cNokogiriXmlNode, "internal_subset", internal_subset, 0);
1811
- rb_define_method(cNokogiriXmlNode, "external_subset", external_subset, 0);
1812
- rb_define_method(cNokogiriXmlNode, "create_internal_subset", create_internal_subset, 3);
1813
- rb_define_method(cNokogiriXmlNode, "create_external_subset", create_external_subset, 3);
1814
- rb_define_method(cNokogiriXmlNode, "pointer_id", pointer_id, 0);
1815
- rb_define_method(cNokogiriXmlNode, "line", line, 0);
1816
- rb_define_method(cNokogiriXmlNode, "line=", set_line, 1);
1817
- rb_define_method(cNokogiriXmlNode, "content", get_native_content, 0);
1818
- rb_define_method(cNokogiriXmlNode, "native_content=", set_native_content, 1);
1819
- rb_define_method(cNokogiriXmlNode, "lang", get_lang, 0);
1820
- rb_define_method(cNokogiriXmlNode, "lang=", set_lang, 1);
1821
2149
 
1822
- rb_define_private_method(cNokogiriXmlNode, "process_xincludes", process_xincludes, 1);
1823
- rb_define_private_method(cNokogiriXmlNode, "in_context", in_context, 2);
1824
2150
  rb_define_private_method(cNokogiriXmlNode, "add_child_node", add_child, 1);
1825
- rb_define_private_method(cNokogiriXmlNode, "add_previous_sibling_node", add_previous_sibling, 1);
1826
2151
  rb_define_private_method(cNokogiriXmlNode, "add_next_sibling_node", add_next_sibling, 1);
1827
- rb_define_private_method(cNokogiriXmlNode, "replace_node", replace, 1);
2152
+ rb_define_private_method(cNokogiriXmlNode, "add_previous_sibling_node", add_previous_sibling, 1);
2153
+ rb_define_private_method(cNokogiriXmlNode, "compare", compare, 1);
1828
2154
  rb_define_private_method(cNokogiriXmlNode, "dump_html", dump_html, 0);
1829
- rb_define_private_method(cNokogiriXmlNode, "native_write_to", native_write_to, 4);
1830
2155
  rb_define_private_method(cNokogiriXmlNode, "get", get, 1);
2156
+ rb_define_private_method(cNokogiriXmlNode, "in_context", in_context, 2);
2157
+ rb_define_private_method(cNokogiriXmlNode, "native_write_to", native_write_to, 4);
2158
+ rb_define_private_method(cNokogiriXmlNode, "process_xincludes", process_xincludes, 1);
2159
+ rb_define_private_method(cNokogiriXmlNode, "replace_node", replace, 1);
1831
2160
  rb_define_private_method(cNokogiriXmlNode, "set", set, 2);
1832
2161
  rb_define_private_method(cNokogiriXmlNode, "set_namespace", set_namespace, 1);
1833
- rb_define_private_method(cNokogiriXmlNode, "compare", compare, 1);
1834
2162
 
1835
2163
  id_decorate = rb_intern("decorate");
1836
2164
  id_decorate_bang = rb_intern("decorate!");
1837
2165
  }
1838
-
1839
- /* vim: set noet sw=4 sws=4 */