nokogiri-maven 1.5.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (278) hide show
  1. data/CHANGELOG.ja.rdoc +544 -0
  2. data/CHANGELOG.rdoc +532 -0
  3. data/Manifest.txt +283 -0
  4. data/README.ja.rdoc +106 -0
  5. data/README.rdoc +174 -0
  6. data/Rakefile +164 -0
  7. data/bin/nokogiri +53 -0
  8. data/ext/java/nokogiri/EncodingHandler.java +124 -0
  9. data/ext/java/nokogiri/HtmlDocument.java +119 -0
  10. data/ext/java/nokogiri/HtmlElementDescription.java +145 -0
  11. data/ext/java/nokogiri/HtmlEntityLookup.java +79 -0
  12. data/ext/java/nokogiri/HtmlSaxParserContext.java +259 -0
  13. data/ext/java/nokogiri/NokogiriService.java +590 -0
  14. data/ext/java/nokogiri/XmlAttr.java +180 -0
  15. data/ext/java/nokogiri/XmlAttributeDecl.java +130 -0
  16. data/ext/java/nokogiri/XmlCdata.java +84 -0
  17. data/ext/java/nokogiri/XmlComment.java +86 -0
  18. data/ext/java/nokogiri/XmlDocument.java +519 -0
  19. data/ext/java/nokogiri/XmlDocumentFragment.java +223 -0
  20. data/ext/java/nokogiri/XmlDtd.java +469 -0
  21. data/ext/java/nokogiri/XmlElement.java +195 -0
  22. data/ext/java/nokogiri/XmlElementContent.java +382 -0
  23. data/ext/java/nokogiri/XmlElementDecl.java +152 -0
  24. data/ext/java/nokogiri/XmlEntityDecl.java +162 -0
  25. data/ext/java/nokogiri/XmlEntityReference.java +97 -0
  26. data/ext/java/nokogiri/XmlNamespace.java +183 -0
  27. data/ext/java/nokogiri/XmlNode.java +1378 -0
  28. data/ext/java/nokogiri/XmlNodeSet.java +267 -0
  29. data/ext/java/nokogiri/XmlProcessingInstruction.java +99 -0
  30. data/ext/java/nokogiri/XmlReader.java +408 -0
  31. data/ext/java/nokogiri/XmlRelaxng.java +144 -0
  32. data/ext/java/nokogiri/XmlSaxParserContext.java +367 -0
  33. data/ext/java/nokogiri/XmlSaxPushParser.java +184 -0
  34. data/ext/java/nokogiri/XmlSchema.java +324 -0
  35. data/ext/java/nokogiri/XmlSyntaxError.java +119 -0
  36. data/ext/java/nokogiri/XmlText.java +119 -0
  37. data/ext/java/nokogiri/XmlXpathContext.java +199 -0
  38. data/ext/java/nokogiri/XsltStylesheet.java +197 -0
  39. data/ext/java/nokogiri/internals/HtmlDomParserContext.java +204 -0
  40. data/ext/java/nokogiri/internals/NokogiriDocumentCache.java +73 -0
  41. data/ext/java/nokogiri/internals/NokogiriErrorHandler.java +86 -0
  42. data/ext/java/nokogiri/internals/NokogiriHandler.java +327 -0
  43. data/ext/java/nokogiri/internals/NokogiriHelpers.java +639 -0
  44. data/ext/java/nokogiri/internals/NokogiriNamespaceCache.java +167 -0
  45. data/ext/java/nokogiri/internals/NokogiriNamespaceContext.java +130 -0
  46. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler.java +74 -0
  47. data/ext/java/nokogiri/internals/NokogiriNonStrictErrorHandler4NekoHtml.java +121 -0
  48. data/ext/java/nokogiri/internals/NokogiriStrictErrorHandler.java +79 -0
  49. data/ext/java/nokogiri/internals/NokogiriXPathFunction.java +141 -0
  50. data/ext/java/nokogiri/internals/NokogiriXPathFunctionResolver.java +73 -0
  51. data/ext/java/nokogiri/internals/NokogiriXPathVariableResolver.java +67 -0
  52. data/ext/java/nokogiri/internals/NokogiriXsltErrorListener.java +86 -0
  53. data/ext/java/nokogiri/internals/ParserContext.java +276 -0
  54. data/ext/java/nokogiri/internals/PushInputStream.java +411 -0
  55. data/ext/java/nokogiri/internals/ReaderNode.java +531 -0
  56. data/ext/java/nokogiri/internals/SaveContextVisitor.java +567 -0
  57. data/ext/java/nokogiri/internals/SchemaErrorHandler.java +76 -0
  58. data/ext/java/nokogiri/internals/XmlDeclHandler.java +42 -0
  59. data/ext/java/nokogiri/internals/XmlDomParser.java +76 -0
  60. data/ext/java/nokogiri/internals/XmlDomParserContext.java +244 -0
  61. data/ext/java/nokogiri/internals/XmlSaxParser.java +65 -0
  62. data/ext/java/nokogiri/internals/XsltExtensionFunction.java +72 -0
  63. data/ext/nokogiri/depend +358 -0
  64. data/ext/nokogiri/extconf.rb +124 -0
  65. data/ext/nokogiri/html_document.c +154 -0
  66. data/ext/nokogiri/html_document.h +10 -0
  67. data/ext/nokogiri/html_element_description.c +276 -0
  68. data/ext/nokogiri/html_element_description.h +10 -0
  69. data/ext/nokogiri/html_entity_lookup.c +32 -0
  70. data/ext/nokogiri/html_entity_lookup.h +8 -0
  71. data/ext/nokogiri/html_sax_parser_context.c +94 -0
  72. data/ext/nokogiri/html_sax_parser_context.h +11 -0
  73. data/ext/nokogiri/nokogiri.c +115 -0
  74. data/ext/nokogiri/nokogiri.h +160 -0
  75. data/ext/nokogiri/xml_attr.c +94 -0
  76. data/ext/nokogiri/xml_attr.h +9 -0
  77. data/ext/nokogiri/xml_attribute_decl.c +70 -0
  78. data/ext/nokogiri/xml_attribute_decl.h +9 -0
  79. data/ext/nokogiri/xml_cdata.c +56 -0
  80. data/ext/nokogiri/xml_cdata.h +9 -0
  81. data/ext/nokogiri/xml_comment.c +54 -0
  82. data/ext/nokogiri/xml_comment.h +9 -0
  83. data/ext/nokogiri/xml_document.c +478 -0
  84. data/ext/nokogiri/xml_document.h +23 -0
  85. data/ext/nokogiri/xml_document_fragment.c +48 -0
  86. data/ext/nokogiri/xml_document_fragment.h +10 -0
  87. data/ext/nokogiri/xml_dtd.c +202 -0
  88. data/ext/nokogiri/xml_dtd.h +10 -0
  89. data/ext/nokogiri/xml_element_content.c +123 -0
  90. data/ext/nokogiri/xml_element_content.h +10 -0
  91. data/ext/nokogiri/xml_element_decl.c +69 -0
  92. data/ext/nokogiri/xml_element_decl.h +9 -0
  93. data/ext/nokogiri/xml_encoding_handler.c +79 -0
  94. data/ext/nokogiri/xml_encoding_handler.h +8 -0
  95. data/ext/nokogiri/xml_entity_decl.c +110 -0
  96. data/ext/nokogiri/xml_entity_decl.h +10 -0
  97. data/ext/nokogiri/xml_entity_reference.c +52 -0
  98. data/ext/nokogiri/xml_entity_reference.h +9 -0
  99. data/ext/nokogiri/xml_io.c +56 -0
  100. data/ext/nokogiri/xml_io.h +11 -0
  101. data/ext/nokogiri/xml_libxml2_hacks.c +112 -0
  102. data/ext/nokogiri/xml_libxml2_hacks.h +12 -0
  103. data/ext/nokogiri/xml_namespace.c +84 -0
  104. data/ext/nokogiri/xml_namespace.h +13 -0
  105. data/ext/nokogiri/xml_node.c +1385 -0
  106. data/ext/nokogiri/xml_node.h +13 -0
  107. data/ext/nokogiri/xml_node_set.c +418 -0
  108. data/ext/nokogiri/xml_node_set.h +9 -0
  109. data/ext/nokogiri/xml_processing_instruction.c +56 -0
  110. data/ext/nokogiri/xml_processing_instruction.h +9 -0
  111. data/ext/nokogiri/xml_reader.c +684 -0
  112. data/ext/nokogiri/xml_reader.h +10 -0
  113. data/ext/nokogiri/xml_relax_ng.c +161 -0
  114. data/ext/nokogiri/xml_relax_ng.h +9 -0
  115. data/ext/nokogiri/xml_sax_parser.c +293 -0
  116. data/ext/nokogiri/xml_sax_parser.h +39 -0
  117. data/ext/nokogiri/xml_sax_parser_context.c +199 -0
  118. data/ext/nokogiri/xml_sax_parser_context.h +10 -0
  119. data/ext/nokogiri/xml_sax_push_parser.c +115 -0
  120. data/ext/nokogiri/xml_sax_push_parser.h +9 -0
  121. data/ext/nokogiri/xml_schema.c +205 -0
  122. data/ext/nokogiri/xml_schema.h +9 -0
  123. data/ext/nokogiri/xml_syntax_error.c +58 -0
  124. data/ext/nokogiri/xml_syntax_error.h +13 -0
  125. data/ext/nokogiri/xml_text.c +50 -0
  126. data/ext/nokogiri/xml_text.h +9 -0
  127. data/ext/nokogiri/xml_xpath_context.c +309 -0
  128. data/ext/nokogiri/xml_xpath_context.h +9 -0
  129. data/ext/nokogiri/xslt_stylesheet.c +264 -0
  130. data/ext/nokogiri/xslt_stylesheet.h +9 -0
  131. data/lib/nokogiri.rb +127 -0
  132. data/lib/nokogiri/css.rb +27 -0
  133. data/lib/nokogiri/css/node.rb +99 -0
  134. data/lib/nokogiri/css/parser.rb +677 -0
  135. data/lib/nokogiri/css/parser.y +237 -0
  136. data/lib/nokogiri/css/parser_extras.rb +91 -0
  137. data/lib/nokogiri/css/syntax_error.rb +7 -0
  138. data/lib/nokogiri/css/tokenizer.rb +152 -0
  139. data/lib/nokogiri/css/tokenizer.rex +55 -0
  140. data/lib/nokogiri/css/xpath_visitor.rb +171 -0
  141. data/lib/nokogiri/decorators/slop.rb +35 -0
  142. data/lib/nokogiri/html.rb +36 -0
  143. data/lib/nokogiri/html/builder.rb +35 -0
  144. data/lib/nokogiri/html/document.rb +213 -0
  145. data/lib/nokogiri/html/document_fragment.rb +41 -0
  146. data/lib/nokogiri/html/element_description.rb +23 -0
  147. data/lib/nokogiri/html/element_description_defaults.rb +671 -0
  148. data/lib/nokogiri/html/entity_lookup.rb +13 -0
  149. data/lib/nokogiri/html/sax/parser.rb +52 -0
  150. data/lib/nokogiri/html/sax/parser_context.rb +16 -0
  151. data/lib/nokogiri/nokogiri.jar +0 -0
  152. data/lib/nokogiri/syntax_error.rb +4 -0
  153. data/lib/nokogiri/version.rb +88 -0
  154. data/lib/nokogiri/xml.rb +67 -0
  155. data/lib/nokogiri/xml/attr.rb +14 -0
  156. data/lib/nokogiri/xml/attribute_decl.rb +18 -0
  157. data/lib/nokogiri/xml/builder.rb +425 -0
  158. data/lib/nokogiri/xml/cdata.rb +11 -0
  159. data/lib/nokogiri/xml/character_data.rb +7 -0
  160. data/lib/nokogiri/xml/document.rb +234 -0
  161. data/lib/nokogiri/xml/document_fragment.rb +98 -0
  162. data/lib/nokogiri/xml/dtd.rb +22 -0
  163. data/lib/nokogiri/xml/element_content.rb +36 -0
  164. data/lib/nokogiri/xml/element_decl.rb +13 -0
  165. data/lib/nokogiri/xml/entity_decl.rb +19 -0
  166. data/lib/nokogiri/xml/namespace.rb +13 -0
  167. data/lib/nokogiri/xml/node.rb +915 -0
  168. data/lib/nokogiri/xml/node/save_options.rb +61 -0
  169. data/lib/nokogiri/xml/node_set.rb +357 -0
  170. data/lib/nokogiri/xml/notation.rb +6 -0
  171. data/lib/nokogiri/xml/parse_options.rb +93 -0
  172. data/lib/nokogiri/xml/pp.rb +2 -0
  173. data/lib/nokogiri/xml/pp/character_data.rb +18 -0
  174. data/lib/nokogiri/xml/pp/node.rb +56 -0
  175. data/lib/nokogiri/xml/processing_instruction.rb +8 -0
  176. data/lib/nokogiri/xml/reader.rb +112 -0
  177. data/lib/nokogiri/xml/relax_ng.rb +32 -0
  178. data/lib/nokogiri/xml/sax.rb +4 -0
  179. data/lib/nokogiri/xml/sax/document.rb +164 -0
  180. data/lib/nokogiri/xml/sax/parser.rb +115 -0
  181. data/lib/nokogiri/xml/sax/parser_context.rb +16 -0
  182. data/lib/nokogiri/xml/sax/push_parser.rb +60 -0
  183. data/lib/nokogiri/xml/schema.rb +63 -0
  184. data/lib/nokogiri/xml/syntax_error.rb +47 -0
  185. data/lib/nokogiri/xml/text.rb +9 -0
  186. data/lib/nokogiri/xml/xpath.rb +10 -0
  187. data/lib/nokogiri/xml/xpath/syntax_error.rb +11 -0
  188. data/lib/nokogiri/xml/xpath_context.rb +16 -0
  189. data/lib/nokogiri/xslt.rb +52 -0
  190. data/lib/nokogiri/xslt/stylesheet.rb +25 -0
  191. data/lib/xsd/xmlparser/nokogiri.rb +90 -0
  192. data/nokogiri_help_responses.md +40 -0
  193. data/tasks/cross_compile.rb +152 -0
  194. data/tasks/nokogiri.org.rb +18 -0
  195. data/tasks/test.rb +94 -0
  196. data/test/css/test_nthiness.rb +159 -0
  197. data/test/css/test_parser.rb +303 -0
  198. data/test/css/test_tokenizer.rb +198 -0
  199. data/test/css/test_xpath_visitor.rb +85 -0
  200. data/test/decorators/test_slop.rb +16 -0
  201. data/test/files/2ch.html +108 -0
  202. data/test/files/address_book.rlx +12 -0
  203. data/test/files/address_book.xml +10 -0
  204. data/test/files/bar/bar.xsd +4 -0
  205. data/test/files/dont_hurt_em_why.xml +422 -0
  206. data/test/files/encoding.html +82 -0
  207. data/test/files/encoding.xhtml +84 -0
  208. data/test/files/exslt.xml +8 -0
  209. data/test/files/exslt.xslt +35 -0
  210. data/test/files/foo/foo.xsd +4 -0
  211. data/test/files/metacharset.html +10 -0
  212. data/test/files/noencoding.html +47 -0
  213. data/test/files/po.xml +32 -0
  214. data/test/files/po.xsd +66 -0
  215. data/test/files/shift_jis.html +10 -0
  216. data/test/files/shift_jis.xml +5 -0
  217. data/test/files/snuggles.xml +3 -0
  218. data/test/files/staff.dtd +10 -0
  219. data/test/files/staff.xml +59 -0
  220. data/test/files/staff.xslt +32 -0
  221. data/test/files/tlm.html +850 -0
  222. data/test/files/valid_bar.xml +2 -0
  223. data/test/helper.rb +173 -0
  224. data/test/html/sax/test_parser.rb +136 -0
  225. data/test/html/sax/test_parser_context.rb +48 -0
  226. data/test/html/test_builder.rb +164 -0
  227. data/test/html/test_document.rb +472 -0
  228. data/test/html/test_document_encoding.rb +138 -0
  229. data/test/html/test_document_fragment.rb +255 -0
  230. data/test/html/test_element_description.rb +100 -0
  231. data/test/html/test_named_characters.rb +14 -0
  232. data/test/html/test_node.rb +190 -0
  233. data/test/html/test_node_encoding.rb +27 -0
  234. data/test/test_convert_xpath.rb +135 -0
  235. data/test/test_css_cache.rb +45 -0
  236. data/test/test_encoding_handler.rb +46 -0
  237. data/test/test_memory_leak.rb +72 -0
  238. data/test/test_nokogiri.rb +132 -0
  239. data/test/test_reader.rb +425 -0
  240. data/test/test_soap4r_sax.rb +52 -0
  241. data/test/test_xslt_transforms.rb +193 -0
  242. data/test/xml/node/test_save_options.rb +28 -0
  243. data/test/xml/node/test_subclass.rb +44 -0
  244. data/test/xml/sax/test_parser.rb +338 -0
  245. data/test/xml/sax/test_parser_context.rb +113 -0
  246. data/test/xml/sax/test_push_parser.rb +156 -0
  247. data/test/xml/test_attr.rb +65 -0
  248. data/test/xml/test_attribute_decl.rb +86 -0
  249. data/test/xml/test_builder.rb +227 -0
  250. data/test/xml/test_cdata.rb +50 -0
  251. data/test/xml/test_comment.rb +29 -0
  252. data/test/xml/test_document.rb +697 -0
  253. data/test/xml/test_document_encoding.rb +26 -0
  254. data/test/xml/test_document_fragment.rb +192 -0
  255. data/test/xml/test_dtd.rb +107 -0
  256. data/test/xml/test_dtd_encoding.rb +33 -0
  257. data/test/xml/test_element_content.rb +56 -0
  258. data/test/xml/test_element_decl.rb +73 -0
  259. data/test/xml/test_entity_decl.rb +122 -0
  260. data/test/xml/test_entity_reference.rb +21 -0
  261. data/test/xml/test_namespace.rb +70 -0
  262. data/test/xml/test_node.rb +917 -0
  263. data/test/xml/test_node_attributes.rb +34 -0
  264. data/test/xml/test_node_encoding.rb +107 -0
  265. data/test/xml/test_node_reparenting.rb +334 -0
  266. data/test/xml/test_node_set.rb +742 -0
  267. data/test/xml/test_parse_options.rb +52 -0
  268. data/test/xml/test_processing_instruction.rb +30 -0
  269. data/test/xml/test_reader_encoding.rb +126 -0
  270. data/test/xml/test_relax_ng.rb +60 -0
  271. data/test/xml/test_schema.rb +94 -0
  272. data/test/xml/test_syntax_error.rb +12 -0
  273. data/test/xml/test_text.rb +47 -0
  274. data/test/xml/test_unparented_node.rb +381 -0
  275. data/test/xml/test_xpath.rb +237 -0
  276. data/test/xslt/test_custom_functions.rb +94 -0
  277. data/test/xslt/test_exception_handling.rb +37 -0
  278. metadata +552 -0
@@ -0,0 +1,12 @@
1
+ #ifndef HAVE_XMLFIRSTELEMENTCHILD
2
+
3
+ #ifndef XML_LIBXML2_HACKS
4
+ #define XML_LIBXML2_HACKS
5
+
6
+ xmlNodePtr xmlFirstElementChild(xmlNodePtr parent);
7
+ xmlNodePtr xmlNextElementSibling(xmlNodePtr node);
8
+ xmlNodePtr xmlLastElementChild(xmlNodePtr parent);
9
+
10
+ #endif
11
+
12
+ #endif
@@ -0,0 +1,84 @@
1
+ #include <xml_namespace.h>
2
+
3
+ VALUE cNokogiriXmlNamespace ;
4
+
5
+ /*
6
+ * call-seq:
7
+ * prefix
8
+ *
9
+ * Get the prefix for this namespace. Returns +nil+ if there is no prefix.
10
+ */
11
+ static VALUE prefix(VALUE self)
12
+ {
13
+ xmlNsPtr ns;
14
+ xmlDocPtr doc;
15
+
16
+ Data_Get_Struct(self, xmlNs, ns);
17
+ if(!ns->prefix) return Qnil;
18
+
19
+ Data_Get_Struct(rb_iv_get(self, "@document"), xmlDoc, doc);
20
+
21
+ return NOKOGIRI_STR_NEW2(ns->prefix);
22
+ }
23
+
24
+ /*
25
+ * call-seq:
26
+ * href
27
+ *
28
+ * Get the href for this namespace
29
+ */
30
+ static VALUE href(VALUE self)
31
+ {
32
+ xmlNsPtr ns;
33
+ xmlDocPtr doc;
34
+
35
+ Data_Get_Struct(self, xmlNs, ns);
36
+ if(!ns->href) return Qnil;
37
+
38
+ Data_Get_Struct(rb_iv_get(self, "@document"), xmlDoc, doc);
39
+
40
+ return NOKOGIRI_STR_NEW2(ns->href);
41
+ }
42
+
43
+ VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node)
44
+ {
45
+ VALUE ns, document, node_cache;
46
+
47
+ assert(doc->_private);
48
+
49
+ if(node->_private)
50
+ return (VALUE)node->_private;
51
+
52
+ ns = Data_Wrap_Struct(cNokogiriXmlNamespace, 0, 0, node);
53
+
54
+ document = DOC_RUBY_OBJECT(doc);
55
+
56
+ node_cache = rb_iv_get(document, "@node_cache");
57
+ rb_ary_push(node_cache, ns);
58
+
59
+ rb_iv_set(ns, "@document", DOC_RUBY_OBJECT(doc));
60
+
61
+ node->_private = (void *)ns;
62
+
63
+ return ns;
64
+ }
65
+
66
+ VALUE Nokogiri_wrap_xml_namespace2(VALUE document, xmlNsPtr node)
67
+ {
68
+ xmlDocPtr doc;
69
+ Data_Get_Struct(document, xmlDoc, doc) ;
70
+ return Nokogiri_wrap_xml_namespace(doc, node);
71
+ }
72
+
73
+
74
+ void init_xml_namespace()
75
+ {
76
+ VALUE nokogiri = rb_define_module("Nokogiri");
77
+ VALUE xml = rb_define_module_under(nokogiri, "XML");
78
+ VALUE klass = rb_define_class_under(xml, "Namespace", rb_cObject);
79
+
80
+ cNokogiriXmlNamespace = klass;
81
+
82
+ rb_define_method(klass, "prefix", prefix, 0);
83
+ rb_define_method(klass, "href", href, 0);
84
+ }
@@ -0,0 +1,13 @@
1
+ #ifndef NOKOGIRI_XML_NAMESPACE
2
+ #define NOKOGIRI_XML_NAMESPACE
3
+
4
+ #include <nokogiri.h>
5
+
6
+ void init_xml_namespace();
7
+
8
+ extern VALUE cNokogiriXmlNamespace ;
9
+
10
+ VALUE Nokogiri_wrap_xml_namespace(xmlDocPtr doc, xmlNsPtr node) ;
11
+ VALUE Nokogiri_wrap_xml_namespace2(VALUE document, xmlNsPtr node) ;
12
+
13
+ #endif
@@ -0,0 +1,1385 @@
1
+ #include <xml_node.h>
2
+
3
+ static ID decorate, decorate_bang;
4
+
5
+ #ifdef DEBUG
6
+ static void debug_node_dealloc(xmlNodePtr x)
7
+ {
8
+ NOKOGIRI_DEBUG_START(x)
9
+ NOKOGIRI_DEBUG_END(x)
10
+ }
11
+ #else
12
+ # define debug_node_dealloc 0
13
+ #endif
14
+
15
+ static void mark(xmlNodePtr node)
16
+ {
17
+ rb_gc_mark(DOC_RUBY_OBJECT(node->doc));
18
+ }
19
+
20
+ /* :nodoc: */
21
+ typedef xmlNodePtr (*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
22
+
23
+ /* :nodoc: */
24
+ static void relink_namespace(xmlNodePtr reparented)
25
+ {
26
+ xmlNodePtr child;
27
+
28
+ /* Avoid segv when relinking against unlinked nodes. */
29
+ if(!reparented->parent) return;
30
+
31
+ /* Make sure that our reparented node has the correct namespaces */
32
+ if(!reparented->ns && reparented->doc != (xmlDocPtr)reparented->parent)
33
+ xmlSetNs(reparented, reparented->parent->ns);
34
+
35
+ /* Search our parents for an existing definition */
36
+ if(reparented->nsDef) {
37
+ xmlNsPtr curr = reparented->nsDef;
38
+ xmlNsPtr prev = NULL;
39
+
40
+ while(curr) {
41
+ xmlNsPtr ns = xmlSearchNsByHref(
42
+ reparented->doc,
43
+ reparented->parent,
44
+ curr->href
45
+ );
46
+ /* If we find the namespace is already declared, remove it from this
47
+ * definition list. */
48
+ if(ns && ns != curr) {
49
+ if (prev) {
50
+ prev->next = curr->next;
51
+ } else {
52
+ reparented->nsDef = curr->next;
53
+ }
54
+ NOKOGIRI_ROOT_NSDEF(curr, reparented->doc);
55
+ } else {
56
+ prev = curr;
57
+ }
58
+ curr = curr->next;
59
+ }
60
+ }
61
+
62
+ /* Only walk all children if there actually is a namespace we need to */
63
+ /* reparent. */
64
+ if(NULL == reparented->ns) return;
65
+
66
+ /* When a node gets reparented, walk it's children to make sure that */
67
+ /* their namespaces are reparented as well. */
68
+ child = reparented->children;
69
+ while(NULL != child) {
70
+ relink_namespace(child);
71
+ child = child->next;
72
+ }
73
+ }
74
+
75
+ /* :nodoc: */
76
+ static xmlNodePtr xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
77
+ {
78
+ xmlNodePtr retval ;
79
+
80
+ retval = xmlReplaceNode(pivot, new_node) ;
81
+
82
+ if (retval == pivot) {
83
+ retval = new_node ; /* return semantics for reparent_node_with */
84
+ }
85
+
86
+ /* work around libxml2 issue: https://bugzilla.gnome.org/show_bug.cgi?id=615612 */
87
+ if (retval->type == XML_TEXT_NODE) {
88
+ if (retval->prev && retval->prev->type == XML_TEXT_NODE) {
89
+ retval = xmlTextMerge(retval->prev, retval);
90
+ }
91
+ if (retval->next && retval->next->type == XML_TEXT_NODE) {
92
+ retval = xmlTextMerge(retval, retval->next);
93
+ }
94
+ }
95
+
96
+ return retval ;
97
+ }
98
+
99
+ /* :nodoc: */
100
+ static VALUE reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
101
+ {
102
+ VALUE reparented_obj ;
103
+ xmlNodePtr reparentee, pivot, reparented, next_text, new_next_text ;
104
+
105
+ if(!rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlNode))
106
+ rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
107
+ if(rb_obj_is_kind_of(reparentee_obj, cNokogiriXmlDocument))
108
+ rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
109
+
110
+ Data_Get_Struct(reparentee_obj, xmlNode, reparentee);
111
+ Data_Get_Struct(pivot_obj, xmlNode, pivot);
112
+
113
+ if(XML_DOCUMENT_NODE == reparentee->type || XML_HTML_DOCUMENT_NODE == reparentee->type)
114
+ rb_raise(rb_eArgError, "cannot reparent a document node");
115
+
116
+ xmlUnlinkNode(reparentee);
117
+
118
+ if (reparentee->doc != pivot->doc || reparentee->type == XML_TEXT_NODE) {
119
+ /*
120
+ * if the reparentee is a text node, there's a very good chance it will be
121
+ * merged with an adjacent text node after being reparented, and in that case
122
+ * libxml will free the underlying C struct.
123
+ *
124
+ * since we clearly have a ruby object which references the underlying
125
+ * memory, we can't let the C struct get freed. let's pickle the original
126
+ * reparentee by rooting it; and then we'll reparent a duplicate of the
127
+ * node that we don't care about preserving.
128
+ *
129
+ * alternatively, if the reparentee is from a different document than the
130
+ * pivot node, libxml2 is going to get confused about which document's
131
+ * "dictionary" the node's strings belong to (this is an otherwise
132
+ * uninteresting libxml2 implementation detail). as a result, we cannot
133
+ * reparent the actual reparentee, so we reparent a duplicate.
134
+ */
135
+ NOKOGIRI_ROOT_NODE(reparentee);
136
+ if (!(reparentee = xmlDocCopyNode(reparentee, pivot->doc, 1))) {
137
+ rb_raise(rb_eRuntimeError, "Could not reparent node (xmlDocCopyNode)");
138
+ }
139
+ }
140
+
141
+ if (reparentee->type == XML_TEXT_NODE && pivot->next && pivot->next->type == XML_TEXT_NODE) {
142
+ /*
143
+ * libxml merges text nodes in a right-to-left fashion, meaning that if
144
+ * there are two text nodes who would be adjacent, the right (or following,
145
+ * or next) node will be merged into the left (or preceding, or previous)
146
+ * node.
147
+ *
148
+ * and by "merged" I mean the string contents will be concatenated onto the
149
+ * left node's contents, and then the node will be freed.
150
+ *
151
+ * which means that if we have a ruby object wrapped around the right node,
152
+ * its memory would be freed out from under it.
153
+ *
154
+ * so, we detect this edge case and unlink-and-root the text node before it gets
155
+ * merged. then we dup the node and insert that duplicate back into the
156
+ * document where the real node was.
157
+ *
158
+ * yes, this is totally lame.
159
+ */
160
+ next_text = pivot->next ;
161
+ new_next_text = xmlDocCopyNode(next_text, pivot->doc, 1) ;
162
+
163
+ xmlUnlinkNode(next_text);
164
+ NOKOGIRI_ROOT_NODE(next_text);
165
+
166
+ xmlAddNextSibling(pivot, new_next_text);
167
+ }
168
+
169
+ if(!(reparented = (*prf)(pivot, reparentee))) {
170
+ rb_raise(rb_eRuntimeError, "Could not reparent node");
171
+ }
172
+
173
+ /*
174
+ * make sure the ruby object is pointed at the just-reparented node, which
175
+ * might be a duplicate (see above) or might be the result of merging
176
+ * adjacent text nodes.
177
+ */
178
+ DATA_PTR(reparentee_obj) = reparented ;
179
+
180
+ relink_namespace(reparented);
181
+
182
+ reparented_obj = Nokogiri_wrap_xml_node(Qnil, reparented);
183
+
184
+ rb_funcall(reparented_obj, decorate_bang, 0);
185
+
186
+ return reparented_obj ;
187
+ }
188
+
189
+
190
+ /*
191
+ * call-seq:
192
+ * document
193
+ *
194
+ * Get the document for this Node
195
+ */
196
+ static VALUE document(VALUE self)
197
+ {
198
+ xmlNodePtr node;
199
+ Data_Get_Struct(self, xmlNode, node);
200
+ return DOC_RUBY_OBJECT(node->doc);
201
+ }
202
+
203
+ /*
204
+ * call-seq:
205
+ * pointer_id
206
+ *
207
+ * Get the internal pointer number
208
+ */
209
+ static VALUE pointer_id(VALUE self)
210
+ {
211
+ xmlNodePtr node;
212
+ Data_Get_Struct(self, xmlNode, node);
213
+
214
+ return INT2NUM((long)(node));
215
+ }
216
+
217
+ /*
218
+ * call-seq:
219
+ * encode_special_chars(string)
220
+ *
221
+ * Encode any special characters in +string+
222
+ */
223
+ static VALUE encode_special_chars(VALUE self, VALUE string)
224
+ {
225
+ xmlNodePtr node;
226
+ xmlChar *encoded;
227
+ VALUE encoded_str;
228
+
229
+ Data_Get_Struct(self, xmlNode, node);
230
+ encoded = xmlEncodeSpecialChars(
231
+ node->doc,
232
+ (const xmlChar *)StringValuePtr(string)
233
+ );
234
+
235
+ encoded_str = NOKOGIRI_STR_NEW2(encoded);
236
+ xmlFree(encoded);
237
+
238
+ return encoded_str;
239
+ }
240
+
241
+ /*
242
+ * call-seq:
243
+ * create_internal_subset(name, external_id, system_id)
244
+ *
245
+ * Create the internal subset of a document.
246
+ *
247
+ * doc.create_internal_subset("chapter", "-//OASIS//DTD DocBook XML//EN", "chapter.dtd")
248
+ * # => <!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML//EN" "chapter.dtd">
249
+ *
250
+ * doc.create_internal_subset("chapter", nil, "chapter.dtd")
251
+ * # => <!DOCTYPE chapter SYSTEM "chapter.dtd">
252
+ */
253
+ static VALUE create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
254
+ {
255
+ xmlNodePtr node;
256
+ xmlDocPtr doc;
257
+ xmlDtdPtr dtd;
258
+
259
+ Data_Get_Struct(self, xmlNode, node);
260
+
261
+ doc = node->doc;
262
+
263
+ if(xmlGetIntSubset(doc))
264
+ rb_raise(rb_eRuntimeError, "Document already has an internal subset");
265
+
266
+ dtd = xmlCreateIntSubset(
267
+ doc,
268
+ NIL_P(name) ? NULL : (const xmlChar *)StringValuePtr(name),
269
+ NIL_P(external_id) ? NULL : (const xmlChar *)StringValuePtr(external_id),
270
+ NIL_P(system_id) ? NULL : (const xmlChar *)StringValuePtr(system_id)
271
+ );
272
+
273
+ if(!dtd) return Qnil;
274
+
275
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
276
+ }
277
+
278
+ /*
279
+ * call-seq:
280
+ * create_external_subset(name, external_id, system_id)
281
+ *
282
+ * Create an external subset
283
+ */
284
+ static VALUE create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_id)
285
+ {
286
+ xmlNodePtr node;
287
+ xmlDocPtr doc;
288
+ xmlDtdPtr dtd;
289
+
290
+ Data_Get_Struct(self, xmlNode, node);
291
+
292
+ doc = node->doc;
293
+
294
+ if(doc->extSubset)
295
+ rb_raise(rb_eRuntimeError, "Document already has an external subset");
296
+
297
+ dtd = xmlNewDtd(
298
+ doc,
299
+ NIL_P(name) ? NULL : (const xmlChar *)StringValuePtr(name),
300
+ NIL_P(external_id) ? NULL : (const xmlChar *)StringValuePtr(external_id),
301
+ NIL_P(system_id) ? NULL : (const xmlChar *)StringValuePtr(system_id)
302
+ );
303
+
304
+ if(!dtd) return Qnil;
305
+
306
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
307
+ }
308
+
309
+ /*
310
+ * call-seq:
311
+ * external_subset
312
+ *
313
+ * Get the external subset
314
+ */
315
+ static VALUE external_subset(VALUE self)
316
+ {
317
+ xmlNodePtr node;
318
+ xmlDocPtr doc;
319
+ xmlDtdPtr dtd;
320
+
321
+ Data_Get_Struct(self, xmlNode, node);
322
+
323
+ if(!node->doc) return Qnil;
324
+
325
+ doc = node->doc;
326
+ dtd = doc->extSubset;
327
+
328
+ if(!dtd) return Qnil;
329
+
330
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
331
+ }
332
+
333
+ /*
334
+ * call-seq:
335
+ * internal_subset
336
+ *
337
+ * Get the internal subset
338
+ */
339
+ static VALUE internal_subset(VALUE self)
340
+ {
341
+ xmlNodePtr node;
342
+ xmlDocPtr doc;
343
+ xmlDtdPtr dtd;
344
+
345
+ Data_Get_Struct(self, xmlNode, node);
346
+
347
+ if(!node->doc) return Qnil;
348
+
349
+ doc = node->doc;
350
+ dtd = xmlGetIntSubset(doc);
351
+
352
+ if(!dtd) return Qnil;
353
+
354
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)dtd);
355
+ }
356
+
357
+ /*
358
+ * call-seq:
359
+ * dup
360
+ *
361
+ * Copy this node. An optional depth may be passed in, but it defaults
362
+ * to a deep copy. 0 is a shallow copy, 1 is a deep copy.
363
+ */
364
+ static VALUE duplicate_node(int argc, VALUE *argv, VALUE self)
365
+ {
366
+ VALUE level;
367
+ xmlNodePtr node, dup;
368
+
369
+ if(rb_scan_args(argc, argv, "01", &level) == 0)
370
+ level = INT2NUM((long)1);
371
+
372
+ Data_Get_Struct(self, xmlNode, node);
373
+
374
+ dup = xmlDocCopyNode(node, node->doc, (int)NUM2INT(level));
375
+ if(dup == NULL) return Qnil;
376
+
377
+ NOKOGIRI_ROOT_NODE(dup);
378
+
379
+ return Nokogiri_wrap_xml_node(rb_obj_class(self), dup);
380
+ }
381
+
382
+ /*
383
+ * call-seq:
384
+ * unlink
385
+ *
386
+ * Unlink this node from its current context.
387
+ */
388
+ static VALUE unlink_node(VALUE self)
389
+ {
390
+ xmlNodePtr node;
391
+ Data_Get_Struct(self, xmlNode, node);
392
+ xmlUnlinkNode(node);
393
+ NOKOGIRI_ROOT_NODE(node);
394
+ return self;
395
+ }
396
+
397
+ /*
398
+ * call-seq:
399
+ * blank?
400
+ *
401
+ * Is this node blank?
402
+ */
403
+ static VALUE blank_eh(VALUE self)
404
+ {
405
+ xmlNodePtr node;
406
+ Data_Get_Struct(self, xmlNode, node);
407
+ return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
408
+ }
409
+
410
+ /*
411
+ * call-seq:
412
+ * next_sibling
413
+ *
414
+ * Returns the next sibling node
415
+ */
416
+ static VALUE next_sibling(VALUE self)
417
+ {
418
+ xmlNodePtr node, sibling;
419
+ Data_Get_Struct(self, xmlNode, node);
420
+
421
+ sibling = node->next;
422
+ if(!sibling) return Qnil;
423
+
424
+ return Nokogiri_wrap_xml_node(Qnil, sibling) ;
425
+ }
426
+
427
+ /*
428
+ * call-seq:
429
+ * previous_sibling
430
+ *
431
+ * Returns the previous sibling node
432
+ */
433
+ static VALUE previous_sibling(VALUE self)
434
+ {
435
+ xmlNodePtr node, sibling;
436
+ Data_Get_Struct(self, xmlNode, node);
437
+
438
+ sibling = node->prev;
439
+ if(!sibling) return Qnil;
440
+
441
+ return Nokogiri_wrap_xml_node(Qnil, sibling);
442
+ }
443
+
444
+ /*
445
+ * call-seq:
446
+ * next_element
447
+ *
448
+ * Returns the next Nokogiri::XML::Element type sibling node.
449
+ */
450
+ static VALUE next_element(VALUE self)
451
+ {
452
+ xmlNodePtr node, sibling;
453
+ Data_Get_Struct(self, xmlNode, node);
454
+
455
+ sibling = xmlNextElementSibling(node);
456
+ if(!sibling) return Qnil;
457
+
458
+ return Nokogiri_wrap_xml_node(Qnil, sibling);
459
+ }
460
+
461
+ /*
462
+ * call-seq:
463
+ * previous_element
464
+ *
465
+ * Returns the previous Nokogiri::XML::Element type sibling node.
466
+ */
467
+ static VALUE previous_element(VALUE self)
468
+ {
469
+ xmlNodePtr node, sibling;
470
+ Data_Get_Struct(self, xmlNode, node);
471
+
472
+ /*
473
+ * note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
474
+ */
475
+ sibling = node->prev;
476
+ if(!sibling) return Qnil;
477
+
478
+ while(sibling && sibling->type != XML_ELEMENT_NODE)
479
+ sibling = sibling->prev;
480
+
481
+ return sibling ? Nokogiri_wrap_xml_node(Qnil, sibling) : Qnil ;
482
+ }
483
+
484
+ /* :nodoc: */
485
+ static VALUE replace(VALUE self, VALUE new_node)
486
+ {
487
+ return reparent_node_with(self, new_node, xmlReplaceNodeWrapper) ;
488
+ }
489
+
490
+ /*
491
+ * call-seq:
492
+ * children
493
+ *
494
+ * Get the list of children for this node as a NodeSet
495
+ */
496
+ static VALUE children(VALUE self)
497
+ {
498
+ xmlNodePtr node;
499
+ xmlNodePtr child;
500
+ xmlNodeSetPtr set;
501
+ VALUE document;
502
+ VALUE node_set;
503
+
504
+ Data_Get_Struct(self, xmlNode, node);
505
+
506
+ child = node->children;
507
+ set = xmlXPathNodeSetCreate(child);
508
+
509
+ document = DOC_RUBY_OBJECT(node->doc);
510
+
511
+ if(!child) return Nokogiri_wrap_xml_node_set(set, document);
512
+
513
+ child = child->next;
514
+ while(NULL != child) {
515
+ xmlXPathNodeSetAddUnique(set, child);
516
+ child = child->next;
517
+ }
518
+
519
+ node_set = Nokogiri_wrap_xml_node_set(set, document);
520
+
521
+ return node_set;
522
+ }
523
+
524
+ /*
525
+ * call-seq:
526
+ * element_children
527
+ *
528
+ * Get the list of children for this node as a NodeSet. All nodes will be
529
+ * element nodes.
530
+ *
531
+ * Example:
532
+ *
533
+ * @doc.root.element_children.all? { |x| x.element? } # => true
534
+ */
535
+ static VALUE element_children(VALUE self)
536
+ {
537
+ xmlNodePtr node;
538
+ xmlNodePtr child;
539
+ xmlNodeSetPtr set;
540
+ VALUE document;
541
+ VALUE node_set;
542
+
543
+ Data_Get_Struct(self, xmlNode, node);
544
+
545
+ child = xmlFirstElementChild(node);
546
+ set = xmlXPathNodeSetCreate(child);
547
+
548
+ document = DOC_RUBY_OBJECT(node->doc);
549
+
550
+ if(!child) return Nokogiri_wrap_xml_node_set(set, document);
551
+
552
+ child = xmlNextElementSibling(child);
553
+ while(NULL != child) {
554
+ xmlXPathNodeSetAddUnique(set, child);
555
+ child = xmlNextElementSibling(child);
556
+ }
557
+
558
+ node_set = Nokogiri_wrap_xml_node_set(set, document);
559
+
560
+ return node_set;
561
+ }
562
+
563
+ /*
564
+ * call-seq:
565
+ * child
566
+ *
567
+ * Returns the child node
568
+ */
569
+ static VALUE child(VALUE self)
570
+ {
571
+ xmlNodePtr node, child;
572
+ Data_Get_Struct(self, xmlNode, node);
573
+
574
+ child = node->children;
575
+ if(!child) return Qnil;
576
+
577
+ return Nokogiri_wrap_xml_node(Qnil, child);
578
+ }
579
+
580
+ /*
581
+ * call-seq:
582
+ * first_element_child
583
+ *
584
+ * Returns the first child node of this node that is an element.
585
+ *
586
+ * Example:
587
+ *
588
+ * @doc.root.first_element_child.element? # => true
589
+ */
590
+ static VALUE first_element_child(VALUE self)
591
+ {
592
+ xmlNodePtr node, child;
593
+ Data_Get_Struct(self, xmlNode, node);
594
+
595
+ child = xmlFirstElementChild(node);
596
+ if(!child) return Qnil;
597
+
598
+ return Nokogiri_wrap_xml_node(Qnil, child);
599
+ }
600
+
601
+ /*
602
+ * call-seq:
603
+ * last_element_child
604
+ *
605
+ * Returns the last child node of this node that is an element.
606
+ *
607
+ * Example:
608
+ *
609
+ * @doc.root.last_element_child.element? # => true
610
+ */
611
+ static VALUE last_element_child(VALUE self)
612
+ {
613
+ xmlNodePtr node, child;
614
+ Data_Get_Struct(self, xmlNode, node);
615
+
616
+ child = xmlLastElementChild(node);
617
+ if(!child) return Qnil;
618
+
619
+ return Nokogiri_wrap_xml_node(Qnil, child);
620
+ }
621
+
622
+ /*
623
+ * call-seq:
624
+ * key?(attribute)
625
+ *
626
+ * Returns true if +attribute+ is set
627
+ */
628
+ static VALUE key_eh(VALUE self, VALUE attribute)
629
+ {
630
+ xmlNodePtr node;
631
+ Data_Get_Struct(self, xmlNode, node);
632
+ if(xmlHasProp(node, (xmlChar *)StringValuePtr(attribute)))
633
+ return Qtrue;
634
+ return Qfalse;
635
+ }
636
+
637
+ /*
638
+ * call-seq:
639
+ * namespaced_key?(attribute, namespace)
640
+ *
641
+ * Returns true if +attribute+ is set with +namespace+
642
+ */
643
+ static VALUE namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
644
+ {
645
+ xmlNodePtr node;
646
+ Data_Get_Struct(self, xmlNode, node);
647
+ if(xmlHasNsProp(node, (xmlChar *)StringValuePtr(attribute),
648
+ NIL_P(namespace) ? NULL : (xmlChar *)StringValuePtr(namespace)))
649
+ return Qtrue;
650
+ return Qfalse;
651
+ }
652
+
653
+ /*
654
+ * call-seq:
655
+ * []=(property, value)
656
+ *
657
+ * Set the +property+ to +value+
658
+ */
659
+ static VALUE set(VALUE self, VALUE property, VALUE value)
660
+ {
661
+ xmlNodePtr node;
662
+ Data_Get_Struct(self, xmlNode, node);
663
+
664
+ xmlSetProp(node, (xmlChar *)StringValuePtr(property),
665
+ (xmlChar *)StringValuePtr(value));
666
+
667
+ return value;
668
+ }
669
+
670
+ /*
671
+ * call-seq:
672
+ * get(attribute)
673
+ *
674
+ * Get the value for +attribute+
675
+ */
676
+ static VALUE get(VALUE self, VALUE attribute)
677
+ {
678
+ xmlNodePtr node;
679
+ xmlChar* propstr ;
680
+ VALUE rval ;
681
+ Data_Get_Struct(self, xmlNode, node);
682
+
683
+ if(NIL_P(attribute)) return Qnil;
684
+
685
+ propstr = xmlGetProp(node, (xmlChar *)StringValuePtr(attribute));
686
+
687
+ if(!propstr) return Qnil;
688
+
689
+ rval = NOKOGIRI_STR_NEW2(propstr);
690
+
691
+ xmlFree(propstr);
692
+ return rval ;
693
+ }
694
+
695
+ /*
696
+ * call-seq:
697
+ * set_namespace(namespace)
698
+ *
699
+ * Set the namespace to +namespace+
700
+ */
701
+ static VALUE set_namespace(VALUE self, VALUE namespace)
702
+ {
703
+ xmlNodePtr node;
704
+ xmlNsPtr ns = NULL;
705
+
706
+ Data_Get_Struct(self, xmlNode, node);
707
+
708
+ if(!NIL_P(namespace))
709
+ Data_Get_Struct(namespace, xmlNs, ns);
710
+
711
+ xmlSetNs(node, ns);
712
+
713
+ return self;
714
+ }
715
+
716
+ /*
717
+ * call-seq:
718
+ * attribute(name)
719
+ *
720
+ * Get the attribute node with +name+
721
+ */
722
+ static VALUE attr(VALUE self, VALUE name)
723
+ {
724
+ xmlNodePtr node;
725
+ xmlAttrPtr prop;
726
+ Data_Get_Struct(self, xmlNode, node);
727
+ prop = xmlHasProp(node, (xmlChar *)StringValuePtr(name));
728
+
729
+ if(! prop) return Qnil;
730
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
731
+ }
732
+
733
+ /*
734
+ * call-seq:
735
+ * attribute_with_ns(name, namespace)
736
+ *
737
+ * Get the attribute node with +name+ and +namespace+
738
+ */
739
+ static VALUE attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
740
+ {
741
+ xmlNodePtr node;
742
+ xmlAttrPtr prop;
743
+ Data_Get_Struct(self, xmlNode, node);
744
+ prop = xmlHasNsProp(node, (xmlChar *)StringValuePtr(name),
745
+ NIL_P(namespace) ? NULL : (xmlChar *)StringValuePtr(namespace));
746
+
747
+ if(! prop) return Qnil;
748
+ return Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop);
749
+ }
750
+
751
+ /*
752
+ * call-seq:
753
+ * attribute_nodes()
754
+ *
755
+ * returns a list containing the Node attributes.
756
+ */
757
+ static VALUE attribute_nodes(VALUE self)
758
+ {
759
+ /* this code in the mode of xmlHasProp() */
760
+ xmlNodePtr node;
761
+ VALUE attr;
762
+
763
+ Data_Get_Struct(self, xmlNode, node);
764
+
765
+ attr = rb_ary_new();
766
+ Nokogiri_xml_node_properties(node, attr);
767
+
768
+ return attr ;
769
+ }
770
+
771
+
772
+ /*
773
+ * call-seq:
774
+ * namespace()
775
+ *
776
+ * returns the default namespace set on this node (as with an "xmlns="
777
+ * attribute), as a Namespace object.
778
+ */
779
+ static VALUE namespace(VALUE self)
780
+ {
781
+ xmlNodePtr node ;
782
+ Data_Get_Struct(self, xmlNode, node);
783
+
784
+ if (node->ns)
785
+ return Nokogiri_wrap_xml_namespace(node->doc, node->ns);
786
+
787
+ return Qnil ;
788
+ }
789
+
790
+ /*
791
+ * call-seq:
792
+ * namespace_definitions()
793
+ *
794
+ * 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=").
795
+ */
796
+ static VALUE namespace_definitions(VALUE self)
797
+ {
798
+ /* this code in the mode of xmlHasProp() */
799
+ xmlNodePtr node ;
800
+ VALUE list;
801
+ xmlNsPtr ns;
802
+
803
+ Data_Get_Struct(self, xmlNode, node);
804
+
805
+ list = rb_ary_new();
806
+
807
+ ns = node->nsDef;
808
+
809
+ if(!ns) return list;
810
+
811
+ while(NULL != ns) {
812
+ rb_ary_push(list, Nokogiri_wrap_xml_namespace(node->doc, ns));
813
+ ns = ns->next;
814
+ }
815
+
816
+ return list;
817
+ }
818
+
819
+ /*
820
+ * call-seq:
821
+ * namespace_scopes()
822
+ *
823
+ * returns namespaces in scope for self -- those defined on self element
824
+ * directly or any ancestor node -- as an array of Namespace objects. Default
825
+ * namespaces ("xmlns=" style) for self are included in this array; Default
826
+ * namespaces for ancestors, however, are not. See also #namespaces
827
+ */
828
+ static VALUE namespace_scopes(VALUE self)
829
+ {
830
+ xmlNodePtr node ;
831
+ VALUE list;
832
+ xmlNsPtr *ns_list;
833
+ int j;
834
+
835
+ Data_Get_Struct(self, xmlNode, node);
836
+
837
+ list = rb_ary_new();
838
+ ns_list = xmlGetNsList(node->doc, node);
839
+
840
+ if(!ns_list) return list;
841
+
842
+ for (j = 0 ; ns_list[j] != NULL ; ++j) {
843
+ rb_ary_push(list, Nokogiri_wrap_xml_namespace(node->doc, ns_list[j]));
844
+ }
845
+
846
+ xmlFree(ns_list);
847
+ return list;
848
+ }
849
+
850
+ /*
851
+ * call-seq:
852
+ * node_type
853
+ *
854
+ * Get the type for this Node
855
+ */
856
+ static VALUE node_type(VALUE self)
857
+ {
858
+ xmlNodePtr node;
859
+ Data_Get_Struct(self, xmlNode, node);
860
+ return INT2NUM((long)node->type);
861
+ }
862
+
863
+ /*
864
+ * call-seq:
865
+ * content=
866
+ *
867
+ * Set the content for this Node
868
+ */
869
+ static VALUE set_content(VALUE self, VALUE content)
870
+ {
871
+ xmlNodePtr node, child, next ;
872
+ Data_Get_Struct(self, xmlNode, node);
873
+
874
+ child = node->children;
875
+ while (NULL != child) {
876
+ next = child->next ;
877
+ xmlUnlinkNode(child) ;
878
+ NOKOGIRI_ROOT_NODE(child) ;
879
+ child = next ;
880
+ }
881
+
882
+ xmlNodeSetContent(node, (xmlChar *)StringValuePtr(content));
883
+ return content;
884
+ }
885
+
886
+ /*
887
+ * call-seq:
888
+ * content
889
+ *
890
+ * Returns the content for this Node
891
+ */
892
+ static VALUE get_content(VALUE self)
893
+ {
894
+ xmlNodePtr node;
895
+ xmlChar * content;
896
+
897
+ Data_Get_Struct(self, xmlNode, node);
898
+
899
+ content = xmlNodeGetContent(node);
900
+ if(content) {
901
+ VALUE rval = NOKOGIRI_STR_NEW2(content);
902
+ xmlFree(content);
903
+ return rval;
904
+ }
905
+ return Qnil;
906
+ }
907
+
908
+ /* :nodoc: */
909
+ static VALUE add_child(VALUE self, VALUE new_child)
910
+ {
911
+ return reparent_node_with(self, new_child, xmlAddChild);
912
+ }
913
+
914
+ /*
915
+ * call-seq:
916
+ * parent
917
+ *
918
+ * Get the parent Node for this Node
919
+ */
920
+ static VALUE get_parent(VALUE self)
921
+ {
922
+ xmlNodePtr node, parent;
923
+ Data_Get_Struct(self, xmlNode, node);
924
+
925
+ parent = node->parent;
926
+ if(!parent) return Qnil;
927
+
928
+ return Nokogiri_wrap_xml_node(Qnil, parent) ;
929
+ }
930
+
931
+ /*
932
+ * call-seq:
933
+ * name=(new_name)
934
+ *
935
+ * Set the name for this Node
936
+ */
937
+ static VALUE set_name(VALUE self, VALUE new_name)
938
+ {
939
+ xmlNodePtr node;
940
+ Data_Get_Struct(self, xmlNode, node);
941
+ xmlNodeSetName(node, (xmlChar*)StringValuePtr(new_name));
942
+ return new_name;
943
+ }
944
+
945
+ /*
946
+ * call-seq:
947
+ * name
948
+ *
949
+ * Returns the name for this Node
950
+ */
951
+ static VALUE get_name(VALUE self)
952
+ {
953
+ xmlNodePtr node;
954
+ Data_Get_Struct(self, xmlNode, node);
955
+ if(node->name)
956
+ return NOKOGIRI_STR_NEW2(node->name);
957
+ return Qnil;
958
+ }
959
+
960
+ /*
961
+ * call-seq:
962
+ * path
963
+ *
964
+ * Returns the path associated with this Node
965
+ */
966
+ static VALUE path(VALUE self)
967
+ {
968
+ xmlNodePtr node;
969
+ xmlChar *path ;
970
+ VALUE rval;
971
+
972
+ Data_Get_Struct(self, xmlNode, node);
973
+
974
+ path = xmlGetNodePath(node);
975
+ rval = NOKOGIRI_STR_NEW2(path);
976
+ xmlFree(path);
977
+ return rval ;
978
+ }
979
+
980
+ /* :nodoc: */
981
+ static VALUE add_next_sibling(VALUE self, VALUE new_sibling)
982
+ {
983
+ return reparent_node_with(self, new_sibling, xmlAddNextSibling) ;
984
+ }
985
+
986
+ /* :nodoc: */
987
+ static VALUE add_previous_sibling(VALUE self, VALUE new_sibling)
988
+ {
989
+ return reparent_node_with(self, new_sibling, xmlAddPrevSibling) ;
990
+ }
991
+
992
+ /*
993
+ * call-seq:
994
+ * native_write_to(io, encoding, options)
995
+ *
996
+ * Write this Node to +io+ with +encoding+ and +options+
997
+ */
998
+ static VALUE native_write_to(
999
+ VALUE self,
1000
+ VALUE io,
1001
+ VALUE encoding,
1002
+ VALUE indent_string,
1003
+ VALUE options
1004
+ ) {
1005
+ xmlNodePtr node;
1006
+ const char * before_indent;
1007
+ xmlSaveCtxtPtr savectx;
1008
+
1009
+ Data_Get_Struct(self, xmlNode, node);
1010
+
1011
+ xmlIndentTreeOutput = 1;
1012
+
1013
+ before_indent = xmlTreeIndentString;
1014
+
1015
+ xmlTreeIndentString = StringValuePtr(indent_string);
1016
+
1017
+ savectx = xmlSaveToIO(
1018
+ (xmlOutputWriteCallback)io_write_callback,
1019
+ (xmlOutputCloseCallback)io_close_callback,
1020
+ (void *)io,
1021
+ RTEST(encoding) ? StringValuePtr(encoding) : NULL,
1022
+ (int)NUM2INT(options)
1023
+ );
1024
+
1025
+ xmlSaveTree(savectx, node);
1026
+ xmlSaveClose(savectx);
1027
+
1028
+ xmlTreeIndentString = before_indent;
1029
+ return io;
1030
+ }
1031
+
1032
+ /*
1033
+ * call-seq:
1034
+ * line
1035
+ *
1036
+ * Returns the line for this Node
1037
+ */
1038
+ static VALUE line(VALUE self)
1039
+ {
1040
+ xmlNodePtr node;
1041
+ Data_Get_Struct(self, xmlNode, node);
1042
+
1043
+ return INT2NUM(xmlGetLineNo(node));
1044
+ }
1045
+
1046
+ /*
1047
+ * call-seq:
1048
+ * add_namespace_definition(prefix, href)
1049
+ *
1050
+ * Adds a namespace definition with +prefix+ using +href+ value. The result is
1051
+ * as if parsed XML for this node had included an attribute
1052
+ * 'xmlns:prefix=value'. A default namespace for this node ("xmlns=") can be
1053
+ * added by passing 'nil' for prefix. Namespaces added this way will not
1054
+ * show up in #attributes, but they will be included as an xmlns attribute
1055
+ * when the node is serialized to XML.
1056
+ */
1057
+ static VALUE add_namespace_definition(VALUE self, VALUE prefix, VALUE href)
1058
+ {
1059
+ xmlNodePtr node, namespacee;
1060
+ xmlNsPtr ns;
1061
+
1062
+ Data_Get_Struct(self, xmlNode, node);
1063
+ namespacee = node ;
1064
+
1065
+ ns = xmlSearchNs(
1066
+ node->doc,
1067
+ node,
1068
+ (const xmlChar *)(NIL_P(prefix) ? NULL : StringValuePtr(prefix))
1069
+ );
1070
+
1071
+ if(!ns) {
1072
+ if (node->type != XML_ELEMENT_NODE) {
1073
+ namespacee = node->parent;
1074
+ }
1075
+ ns = xmlNewNs(
1076
+ namespacee,
1077
+ (const xmlChar *)StringValuePtr(href),
1078
+ (const xmlChar *)(NIL_P(prefix) ? NULL : StringValuePtr(prefix))
1079
+ );
1080
+ }
1081
+
1082
+ if (!ns) return Qnil ;
1083
+
1084
+ if(NIL_P(prefix) || node != namespacee) xmlSetNs(node, ns);
1085
+
1086
+ return Nokogiri_wrap_xml_namespace(node->doc, ns);
1087
+ }
1088
+
1089
+ /*
1090
+ * call-seq:
1091
+ * new(name, document)
1092
+ *
1093
+ * Create a new node with +name+ sharing GC lifecycle with +document+
1094
+ */
1095
+ static VALUE new(int argc, VALUE *argv, VALUE klass)
1096
+ {
1097
+ xmlDocPtr doc;
1098
+ xmlNodePtr node;
1099
+ VALUE name;
1100
+ VALUE document;
1101
+ VALUE rest;
1102
+ VALUE rb_node;
1103
+
1104
+ rb_scan_args(argc, argv, "2*", &name, &document, &rest);
1105
+
1106
+ Data_Get_Struct(document, xmlDoc, doc);
1107
+
1108
+ node = xmlNewNode(NULL, (xmlChar *)StringValuePtr(name));
1109
+ node->doc = doc->doc;
1110
+ NOKOGIRI_ROOT_NODE(node);
1111
+
1112
+ rb_node = Nokogiri_wrap_xml_node(
1113
+ klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
1114
+ node
1115
+ );
1116
+ rb_obj_call_init(rb_node, argc, argv);
1117
+
1118
+ if(rb_block_given_p()) rb_yield(rb_node);
1119
+
1120
+ return rb_node;
1121
+ }
1122
+
1123
+ /*
1124
+ * call-seq:
1125
+ * dump_html
1126
+ *
1127
+ * Returns the Node as html.
1128
+ */
1129
+ static VALUE dump_html(VALUE self)
1130
+ {
1131
+ xmlBufferPtr buf ;
1132
+ xmlNodePtr node ;
1133
+ VALUE html;
1134
+
1135
+ Data_Get_Struct(self, xmlNode, node);
1136
+
1137
+ buf = xmlBufferCreate() ;
1138
+ htmlNodeDump(buf, node->doc, node);
1139
+ html = NOKOGIRI_STR_NEW2(buf->content);
1140
+ xmlBufferFree(buf);
1141
+ return html ;
1142
+ }
1143
+
1144
+ /*
1145
+ * call-seq:
1146
+ * compare(other)
1147
+ *
1148
+ * Compare this Node to +other+ with respect to their Document
1149
+ */
1150
+ static VALUE compare(VALUE self, VALUE _other)
1151
+ {
1152
+ xmlNodePtr node, other;
1153
+ Data_Get_Struct(self, xmlNode, node);
1154
+ Data_Get_Struct(_other, xmlNode, other);
1155
+
1156
+ return INT2NUM((long)xmlXPathCmpNodes(other, node));
1157
+ }
1158
+
1159
+
1160
+ /* TODO: DOCUMENT ME */
1161
+ static VALUE in_context(VALUE self, VALUE _str, VALUE _options)
1162
+ {
1163
+ xmlNodePtr node;
1164
+ xmlNodePtr list;
1165
+ xmlNodePtr child_iter;
1166
+ xmlNodeSetPtr set;
1167
+ xmlParserErrors error;
1168
+ VALUE doc, err;
1169
+
1170
+ Data_Get_Struct(self, xmlNode, node);
1171
+
1172
+ doc = DOC_RUBY_OBJECT(node->doc);
1173
+ err = rb_iv_get(doc, "@errors");
1174
+
1175
+ xmlSetStructuredErrorFunc((void *)err, Nokogiri_error_array_pusher);
1176
+
1177
+ /* Twiddle global variable because of a bug in libxml2.
1178
+ * http://git.gnome.org/browse/libxml2/commit/?id=e20fb5a72c83cbfc8e4a8aa3943c6be8febadab7
1179
+ */
1180
+ #ifndef HTML_PARSE_NOIMPLIED
1181
+ htmlHandleOmittedElem(0);
1182
+ #endif
1183
+
1184
+ error = xmlParseInNodeContext(
1185
+ node,
1186
+ StringValuePtr(_str),
1187
+ (int)RSTRING_LEN(_str),
1188
+ (int)NUM2INT(_options),
1189
+ &list);
1190
+
1191
+ /* make sure parent/child pointers are coherent so an unlink will work properly (#331) */
1192
+ child_iter = node->doc->children ;
1193
+ while (child_iter) {
1194
+ if (child_iter->parent != (xmlNodePtr)node->doc)
1195
+ child_iter->parent = (xmlNodePtr)node->doc ;
1196
+ child_iter = child_iter->next ;
1197
+ }
1198
+
1199
+ #ifndef HTML_PARSE_NOIMPLIED
1200
+ htmlHandleOmittedElem(1);
1201
+ #endif
1202
+
1203
+ xmlSetStructuredErrorFunc(NULL, NULL);
1204
+
1205
+ /* FIXME: This probably needs to handle more constants... */
1206
+ switch(error) {
1207
+ case XML_ERR_OK:
1208
+ break;
1209
+
1210
+ case XML_ERR_INTERNAL_ERROR:
1211
+ case XML_ERR_NO_MEMORY:
1212
+ rb_raise(rb_eRuntimeError, "error parsing fragment (%d)", error);
1213
+ break;
1214
+
1215
+ default:
1216
+ break;
1217
+ }
1218
+
1219
+ set = xmlXPathNodeSetCreate(NULL);
1220
+
1221
+ while(list) {
1222
+ xmlXPathNodeSetAddUnique(set, list);
1223
+ list = list->next;
1224
+ }
1225
+
1226
+ return Nokogiri_wrap_xml_node_set(set, doc);
1227
+ }
1228
+
1229
+
1230
+ VALUE Nokogiri_wrap_xml_node(VALUE klass, xmlNodePtr node)
1231
+ {
1232
+ VALUE document = Qnil ;
1233
+ VALUE node_cache = Qnil ;
1234
+ VALUE rb_node = Qnil ;
1235
+ int node_has_a_document = 0 ;
1236
+ void (*mark_method)(xmlNodePtr) = NULL ;
1237
+
1238
+ assert(node);
1239
+
1240
+ if(node->type == XML_DOCUMENT_NODE || node->type == XML_HTML_DOCUMENT_NODE)
1241
+ return DOC_RUBY_OBJECT(node->doc);
1242
+
1243
+ if(NULL != node->_private) return (VALUE)node->_private;
1244
+
1245
+ if(!RTEST(klass)) {
1246
+ switch(node->type)
1247
+ {
1248
+ case XML_ELEMENT_NODE:
1249
+ klass = cNokogiriXmlElement;
1250
+ break;
1251
+ case XML_TEXT_NODE:
1252
+ klass = cNokogiriXmlText;
1253
+ break;
1254
+ case XML_ATTRIBUTE_NODE:
1255
+ klass = cNokogiriXmlAttr;
1256
+ break;
1257
+ case XML_ENTITY_REF_NODE:
1258
+ klass = cNokogiriXmlEntityReference;
1259
+ break;
1260
+ case XML_COMMENT_NODE:
1261
+ klass = cNokogiriXmlComment;
1262
+ break;
1263
+ case XML_DOCUMENT_FRAG_NODE:
1264
+ klass = cNokogiriXmlDocumentFragment;
1265
+ break;
1266
+ case XML_PI_NODE:
1267
+ klass = cNokogiriXmlProcessingInstruction;
1268
+ break;
1269
+ case XML_ENTITY_DECL:
1270
+ klass = cNokogiriXmlEntityDecl;
1271
+ break;
1272
+ case XML_CDATA_SECTION_NODE:
1273
+ klass = cNokogiriXmlCData;
1274
+ break;
1275
+ case XML_DTD_NODE:
1276
+ klass = cNokogiriXmlDtd;
1277
+ break;
1278
+ case XML_ATTRIBUTE_DECL:
1279
+ klass = cNokogiriXmlAttributeDecl;
1280
+ break;
1281
+ case XML_ELEMENT_DECL:
1282
+ klass = cNokogiriXmlElementDecl;
1283
+ break;
1284
+ default:
1285
+ klass = cNokogiriXmlNode;
1286
+ }
1287
+ }
1288
+
1289
+ /* It's OK if the node doesn't have a fully-realized document (as in XML::Reader). */
1290
+ /* see https://github.com/tenderlove/nokogiri/issues/95 */
1291
+ /* and https://github.com/tenderlove/nokogiri/issues/439 */
1292
+ node_has_a_document = (DOC_RUBY_OBJECT_TEST(node->doc) && DOC_RUBY_OBJECT(node->doc)) ? 1 : 0 ;
1293
+ mark_method = node_has_a_document ? mark : NULL ;
1294
+
1295
+ rb_node = Data_Wrap_Struct(klass, mark_method, debug_node_dealloc, node) ;
1296
+ node->_private = (void *)rb_node;
1297
+
1298
+ if (node_has_a_document) {
1299
+ document = DOC_RUBY_OBJECT(node->doc);
1300
+ node_cache = DOC_NODE_CACHE(node->doc);
1301
+ rb_ary_push(node_cache, rb_node);
1302
+ rb_funcall(document, decorate, 1, rb_node);
1303
+ }
1304
+
1305
+ return rb_node ;
1306
+ }
1307
+
1308
+
1309
+ void Nokogiri_xml_node_properties(xmlNodePtr node, VALUE attr_list)
1310
+ {
1311
+ xmlAttrPtr prop;
1312
+ prop = node->properties ;
1313
+ while (prop != NULL) {
1314
+ rb_ary_push(attr_list, Nokogiri_wrap_xml_node(Qnil, (xmlNodePtr)prop));
1315
+ prop = prop->next ;
1316
+ }
1317
+ }
1318
+
1319
+ VALUE cNokogiriXmlNode ;
1320
+ VALUE cNokogiriXmlElement ;
1321
+
1322
+ void init_xml_node()
1323
+ {
1324
+ VALUE nokogiri = rb_define_module("Nokogiri");
1325
+ VALUE xml = rb_define_module_under(nokogiri, "XML");
1326
+ VALUE klass = rb_define_class_under(xml, "Node", rb_cObject);
1327
+
1328
+ cNokogiriXmlNode = klass;
1329
+
1330
+ cNokogiriXmlElement = rb_define_class_under(xml, "Element", klass);
1331
+
1332
+ rb_define_singleton_method(klass, "new", new, -1);
1333
+
1334
+ rb_define_method(klass, "add_namespace_definition", add_namespace_definition, 2);
1335
+ rb_define_method(klass, "node_name", get_name, 0);
1336
+ rb_define_method(klass, "document", document, 0);
1337
+ rb_define_method(klass, "node_name=", set_name, 1);
1338
+ rb_define_method(klass, "parent", get_parent, 0);
1339
+ rb_define_method(klass, "child", child, 0);
1340
+ rb_define_method(klass, "first_element_child", first_element_child, 0);
1341
+ rb_define_method(klass, "last_element_child", last_element_child, 0);
1342
+ rb_define_method(klass, "children", children, 0);
1343
+ rb_define_method(klass, "element_children", element_children, 0);
1344
+ rb_define_method(klass, "next_sibling", next_sibling, 0);
1345
+ rb_define_method(klass, "previous_sibling", previous_sibling, 0);
1346
+ rb_define_method(klass, "next_element", next_element, 0);
1347
+ rb_define_method(klass, "previous_element", previous_element, 0);
1348
+ rb_define_method(klass, "node_type", node_type, 0);
1349
+ rb_define_method(klass, "content", get_content, 0);
1350
+ rb_define_method(klass, "path", path, 0);
1351
+ rb_define_method(klass, "key?", key_eh, 1);
1352
+ rb_define_method(klass, "namespaced_key?", namespaced_key_eh, 2);
1353
+ rb_define_method(klass, "blank?", blank_eh, 0);
1354
+ rb_define_method(klass, "[]=", set, 2);
1355
+ rb_define_method(klass, "attribute_nodes", attribute_nodes, 0);
1356
+ rb_define_method(klass, "attribute", attr, 1);
1357
+ rb_define_method(klass, "attribute_with_ns", attribute_with_ns, 2);
1358
+ rb_define_method(klass, "namespace", namespace, 0);
1359
+ rb_define_method(klass, "namespace_definitions", namespace_definitions, 0);
1360
+ rb_define_method(klass, "namespace_scopes", namespace_scopes, 0);
1361
+ rb_define_method(klass, "encode_special_chars", encode_special_chars, 1);
1362
+ rb_define_method(klass, "dup", duplicate_node, -1);
1363
+ rb_define_method(klass, "unlink", unlink_node, 0);
1364
+ rb_define_method(klass, "internal_subset", internal_subset, 0);
1365
+ rb_define_method(klass, "external_subset", external_subset, 0);
1366
+ rb_define_method(klass, "create_internal_subset", create_internal_subset, 3);
1367
+ rb_define_method(klass, "create_external_subset", create_external_subset, 3);
1368
+ rb_define_method(klass, "pointer_id", pointer_id, 0);
1369
+ rb_define_method(klass, "line", line, 0);
1370
+
1371
+ rb_define_private_method(klass, "in_context", in_context, 2);
1372
+ rb_define_private_method(klass, "add_child_node", add_child, 1);
1373
+ rb_define_private_method(klass, "add_previous_sibling_node", add_previous_sibling, 1);
1374
+ rb_define_private_method(klass, "add_next_sibling_node", add_next_sibling, 1);
1375
+ rb_define_private_method(klass, "replace_node", replace, 1);
1376
+ rb_define_private_method(klass, "dump_html", dump_html, 0);
1377
+ rb_define_private_method(klass, "native_write_to", native_write_to, 4);
1378
+ rb_define_private_method(klass, "native_content=", set_content, 1);
1379
+ rb_define_private_method(klass, "get", get, 1);
1380
+ rb_define_private_method(klass, "set_namespace", set_namespace, 1);
1381
+ rb_define_private_method(klass, "compare", compare, 1);
1382
+
1383
+ decorate = rb_intern("decorate");
1384
+ decorate_bang = rb_intern("decorate!");
1385
+ }