nokogiri 1.12.5 → 1.14.3
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.
- checksums.yaml +4 -4
- data/Gemfile +41 -0
- data/LICENSE-DEPENDENCIES.md +830 -509
- data/LICENSE.md +1 -1
- data/README.md +23 -14
- data/bin/nokogiri +63 -50
- data/dependencies.yml +33 -66
- data/ext/nokogiri/extconf.rb +159 -63
- data/ext/nokogiri/gumbo.c +21 -11
- data/ext/nokogiri/html4_document.c +2 -2
- data/ext/nokogiri/html4_element_description.c +1 -1
- data/ext/nokogiri/html4_entity_lookup.c +2 -2
- data/ext/nokogiri/html4_sax_parser_context.c +3 -9
- data/ext/nokogiri/html4_sax_push_parser.c +1 -1
- data/ext/nokogiri/nokogiri.c +38 -51
- data/ext/nokogiri/nokogiri.h +26 -14
- data/ext/nokogiri/test_global_handlers.c +1 -1
- data/ext/nokogiri/xml_attr.c +3 -3
- data/ext/nokogiri/xml_attribute_decl.c +5 -5
- data/ext/nokogiri/xml_cdata.c +3 -3
- data/ext/nokogiri/xml_comment.c +1 -1
- data/ext/nokogiri/xml_document.c +53 -44
- data/ext/nokogiri/xml_document_fragment.c +1 -3
- data/ext/nokogiri/xml_dtd.c +11 -11
- data/ext/nokogiri/xml_element_content.c +3 -3
- data/ext/nokogiri/xml_element_decl.c +5 -5
- data/ext/nokogiri/xml_encoding_handler.c +28 -14
- data/ext/nokogiri/xml_entity_decl.c +6 -6
- data/ext/nokogiri/xml_entity_reference.c +1 -1
- data/ext/nokogiri/xml_namespace.c +80 -14
- data/ext/nokogiri/xml_node.c +982 -396
- data/ext/nokogiri/xml_node_set.c +4 -6
- data/ext/nokogiri/xml_processing_instruction.c +1 -1
- data/ext/nokogiri/xml_reader.c +133 -32
- data/ext/nokogiri/xml_relax_ng.c +1 -3
- data/ext/nokogiri/xml_sax_parser.c +23 -17
- data/ext/nokogiri/xml_sax_parser_context.c +11 -9
- data/ext/nokogiri/xml_sax_push_parser.c +1 -3
- data/ext/nokogiri/xml_schema.c +4 -6
- data/ext/nokogiri/xml_syntax_error.c +1 -1
- data/ext/nokogiri/xml_text.c +2 -2
- data/ext/nokogiri/xml_xpath_context.c +144 -114
- data/ext/nokogiri/xslt_stylesheet.c +122 -23
- data/gumbo-parser/Makefile +10 -0
- data/gumbo-parser/src/attribute.h +1 -1
- data/gumbo-parser/src/error.c +2 -2
- data/gumbo-parser/src/error.h +1 -1
- data/gumbo-parser/src/foreign_attrs.c +2 -2
- data/gumbo-parser/src/{gumbo.h → nokogiri_gumbo.h} +1 -0
- data/gumbo-parser/src/parser.c +8 -16
- data/gumbo-parser/src/replacement.h +1 -1
- data/gumbo-parser/src/string_buffer.h +1 -1
- data/gumbo-parser/src/string_piece.c +1 -1
- data/gumbo-parser/src/svg_attrs.c +2 -2
- data/gumbo-parser/src/svg_tags.c +2 -2
- data/gumbo-parser/src/tag.c +2 -1
- data/gumbo-parser/src/tag_lookup.c +7 -7
- data/gumbo-parser/src/tag_lookup.gperf +1 -0
- data/gumbo-parser/src/tag_lookup.h +1 -1
- data/gumbo-parser/src/token_buffer.h +1 -1
- data/gumbo-parser/src/tokenizer.c +1 -1
- data/gumbo-parser/src/tokenizer.h +1 -1
- data/gumbo-parser/src/utf8.c +1 -1
- data/gumbo-parser/src/utf8.h +1 -1
- data/gumbo-parser/src/util.c +1 -3
- data/gumbo-parser/src/util.h +4 -0
- data/gumbo-parser/src/vector.h +1 -1
- data/lib/nokogiri/class_resolver.rb +67 -0
- data/lib/nokogiri/css/node.rb +9 -8
- data/lib/nokogiri/css/parser.rb +360 -341
- data/lib/nokogiri/css/parser.y +249 -244
- data/lib/nokogiri/css/parser_extras.rb +22 -20
- data/lib/nokogiri/css/syntax_error.rb +1 -0
- data/lib/nokogiri/css/tokenizer.rb +4 -3
- data/lib/nokogiri/css/tokenizer.rex +3 -2
- data/lib/nokogiri/css/xpath_visitor.rb +184 -85
- data/lib/nokogiri/css.rb +44 -6
- data/lib/nokogiri/decorators/slop.rb +8 -7
- data/lib/nokogiri/encoding_handler.rb +57 -0
- data/lib/nokogiri/extension.rb +4 -3
- data/lib/nokogiri/gumbo.rb +1 -0
- data/lib/nokogiri/html.rb +16 -10
- data/lib/nokogiri/html4/builder.rb +1 -0
- data/lib/nokogiri/html4/document.rb +56 -164
- data/lib/nokogiri/html4/document_fragment.rb +11 -7
- data/lib/nokogiri/html4/element_description.rb +1 -0
- data/lib/nokogiri/html4/element_description_defaults.rb +432 -532
- data/lib/nokogiri/html4/encoding_reader.rb +121 -0
- data/lib/nokogiri/html4/entity_lookup.rb +2 -1
- data/lib/nokogiri/html4/sax/parser.rb +5 -2
- data/lib/nokogiri/html4/sax/parser_context.rb +1 -0
- data/lib/nokogiri/html4/sax/push_parser.rb +7 -7
- data/lib/nokogiri/html4.rb +12 -5
- data/lib/nokogiri/html5/document.rb +126 -32
- data/lib/nokogiri/html5/document_fragment.rb +14 -4
- data/lib/nokogiri/html5/node.rb +12 -7
- data/lib/nokogiri/html5.rb +138 -222
- data/lib/nokogiri/jruby/dependencies.rb +2 -19
- data/lib/nokogiri/jruby/nokogiri_jars.rb +43 -0
- data/lib/nokogiri/syntax_error.rb +1 -0
- data/lib/nokogiri/version/constant.rb +2 -1
- data/lib/nokogiri/version/info.rb +32 -24
- data/lib/nokogiri/version.rb +1 -0
- data/lib/nokogiri/xml/attr.rb +54 -3
- data/lib/nokogiri/xml/attribute_decl.rb +2 -1
- data/lib/nokogiri/xml/builder.rb +35 -33
- data/lib/nokogiri/xml/cdata.rb +2 -1
- data/lib/nokogiri/xml/character_data.rb +1 -0
- data/lib/nokogiri/xml/document.rb +232 -143
- data/lib/nokogiri/xml/document_fragment.rb +88 -42
- data/lib/nokogiri/xml/dtd.rb +3 -2
- data/lib/nokogiri/xml/element_content.rb +1 -0
- data/lib/nokogiri/xml/element_decl.rb +2 -1
- data/lib/nokogiri/xml/entity_decl.rb +3 -2
- data/lib/nokogiri/xml/entity_reference.rb +1 -0
- data/lib/nokogiri/xml/namespace.rb +44 -0
- data/lib/nokogiri/xml/node/save_options.rb +14 -8
- data/lib/nokogiri/xml/node.rb +708 -383
- data/lib/nokogiri/xml/node_set.rb +134 -59
- data/lib/nokogiri/xml/notation.rb +12 -0
- data/lib/nokogiri/xml/parse_options.rb +140 -56
- data/lib/nokogiri/xml/pp/character_data.rb +8 -6
- data/lib/nokogiri/xml/pp/node.rb +26 -26
- data/lib/nokogiri/xml/pp.rb +1 -0
- data/lib/nokogiri/xml/processing_instruction.rb +3 -1
- data/lib/nokogiri/xml/reader.rb +20 -24
- data/lib/nokogiri/xml/relax_ng.rb +1 -0
- data/lib/nokogiri/xml/sax/document.rb +20 -19
- data/lib/nokogiri/xml/sax/parser.rb +38 -36
- data/lib/nokogiri/xml/sax/parser_context.rb +7 -3
- data/lib/nokogiri/xml/sax/push_parser.rb +5 -5
- data/lib/nokogiri/xml/sax.rb +1 -0
- data/lib/nokogiri/xml/schema.rb +7 -6
- data/lib/nokogiri/xml/searchable.rb +93 -62
- data/lib/nokogiri/xml/syntax_error.rb +5 -4
- data/lib/nokogiri/xml/text.rb +1 -0
- data/lib/nokogiri/xml/xpath/syntax_error.rb +2 -1
- data/lib/nokogiri/xml/xpath.rb +12 -0
- data/lib/nokogiri/xml/xpath_context.rb +2 -3
- data/lib/nokogiri/xml.rb +4 -3
- data/lib/nokogiri/xslt/stylesheet.rb +1 -0
- data/lib/nokogiri/xslt.rb +21 -13
- data/lib/nokogiri.rb +22 -27
- data/lib/xsd/xmlparser/nokogiri.rb +28 -25
- data/patches/libxml2/0009-allow-wildcard-namespaces.patch +77 -0
- data/patches/libxslt/0001-update-automake-files-for-arm64.patch +2445 -1919
- data/ports/archives/libxml2-2.10.4.tar.xz +0 -0
- data/ports/archives/libxslt-1.1.37.tar.xz +0 -0
- metadata +20 -171
- data/patches/libxml2/0004-use-glibc-strlen.patch +0 -53
- data/patches/libxml2/0005-avoid-isnan-isinf.patch +0 -81
- data/patches/libxml2/0006-update-automake-files-for-arm64.patch +0 -2511
- data/patches/libxml2/0007-Fix-XPath-recursion-limit.patch +0 -31
- data/patches/libxslt/0002-Fix-xml2-config-check-in-configure-script.patch +0 -19
- data/ports/archives/libxml2-2.9.12.tar.gz +0 -0
- data/ports/archives/libxslt-1.1.34.tar.gz +0 -0
data/ext/nokogiri/xml_node.c
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
#include <nokogiri.h>
|
2
2
|
|
3
|
-
|
3
|
+
#include <stdbool.h>
|
4
|
+
|
5
|
+
// :stopdoc:
|
4
6
|
|
7
|
+
VALUE cNokogiriXmlNode ;
|
5
8
|
static ID id_decorate, id_decorate_bang;
|
6
9
|
|
7
|
-
|
8
|
-
static void
|
9
|
-
debug_node_dealloc(xmlNodePtr x)
|
10
|
-
{
|
11
|
-
NOKOGIRI_DEBUG_START(x)
|
12
|
-
NOKOGIRI_DEBUG_END(x)
|
13
|
-
}
|
14
|
-
#else
|
15
|
-
# define debug_node_dealloc 0
|
16
|
-
#endif
|
10
|
+
typedef xmlNodePtr(*pivot_reparentee_func)(xmlNodePtr, xmlNodePtr);
|
17
11
|
|
18
12
|
static void
|
19
|
-
|
13
|
+
_xml_node_mark(void *ptr)
|
20
14
|
{
|
15
|
+
xmlNodePtr node = ptr;
|
16
|
+
|
17
|
+
if (!DOC_RUBY_OBJECT_TEST(node->doc)) {
|
18
|
+
return;
|
19
|
+
}
|
20
|
+
|
21
21
|
xmlDocPtr doc = node->doc;
|
22
22
|
if (doc->type == XML_DOCUMENT_NODE || doc->type == XML_HTML_DOCUMENT_NODE) {
|
23
23
|
if (DOC_RUBY_OBJECT_TEST(doc)) {
|
@@ -28,10 +28,29 @@ mark(xmlNodePtr node)
|
|
28
28
|
}
|
29
29
|
}
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
#ifdef HAVE_RB_GC_LOCATION
|
32
|
+
static void
|
33
|
+
_xml_node_update_references(void *ptr)
|
34
|
+
{
|
35
|
+
xmlNodePtr node = ptr;
|
36
|
+
|
37
|
+
if (node->_private) {
|
38
|
+
node->_private = (void *)rb_gc_location((VALUE)node->_private);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
#else
|
42
|
+
# define _xml_node_update_references 0
|
43
|
+
#endif
|
44
|
+
|
45
|
+
static const rb_data_type_t nokogiri_node_type = {
|
46
|
+
"Nokogiri/XMLNode",
|
47
|
+
{_xml_node_mark, 0, 0, _xml_node_update_references},
|
48
|
+
0, 0,
|
49
|
+
#ifdef RUBY_TYPED_FREE_IMMEDIATELY
|
50
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
51
|
+
#endif
|
52
|
+
};
|
33
53
|
|
34
|
-
/* :nodoc: */
|
35
54
|
static void
|
36
55
|
relink_namespace(xmlNodePtr reparented)
|
37
56
|
{
|
@@ -143,7 +162,9 @@ relink_namespace(xmlNodePtr reparented)
|
|
143
162
|
}
|
144
163
|
}
|
145
164
|
|
146
|
-
|
165
|
+
|
166
|
+
/* internal function meant to wrap xmlReplaceNode
|
167
|
+
and fix some issues we have with libxml2 merging nodes */
|
147
168
|
static xmlNodePtr
|
148
169
|
xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
|
149
170
|
{
|
@@ -168,7 +189,18 @@ xmlReplaceNodeWrapper(xmlNodePtr pivot, xmlNodePtr new_node)
|
|
168
189
|
return retval ;
|
169
190
|
}
|
170
191
|
|
171
|
-
|
192
|
+
|
193
|
+
static void
|
194
|
+
raise_if_ancestor_of_self(xmlNodePtr self)
|
195
|
+
{
|
196
|
+
for (xmlNodePtr ancestor = self->parent ; ancestor ; ancestor = ancestor->parent) {
|
197
|
+
if (self == ancestor) {
|
198
|
+
rb_raise(rb_eRuntimeError, "cycle detected: node '%s' is an ancestor of itself", self->name);
|
199
|
+
}
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
|
172
204
|
static VALUE
|
173
205
|
reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func prf)
|
174
206
|
{
|
@@ -183,8 +215,8 @@ reparent_node_with(VALUE pivot_obj, VALUE reparentee_obj, pivot_reparentee_func
|
|
183
215
|
rb_raise(rb_eArgError, "node must be a Nokogiri::XML::Node");
|
184
216
|
}
|
185
217
|
|
186
|
-
|
187
|
-
|
218
|
+
Noko_Node_Get_Struct(reparentee_obj, xmlNode, reparentee);
|
219
|
+
Noko_Node_Get_Struct(pivot_obj, xmlNode, pivot);
|
188
220
|
|
189
221
|
/*
|
190
222
|
* Check if nodes given are appropriate to have a parent-child
|
@@ -357,49 +389,421 @@ ok:
|
|
357
389
|
* adjacent text nodes.
|
358
390
|
*/
|
359
391
|
DATA_PTR(reparentee_obj) = reparented ;
|
360
|
-
|
361
|
-
relink_namespace(reparented);
|
362
|
-
|
363
392
|
reparented_obj = noko_xml_node_wrap(Qnil, reparented);
|
364
393
|
|
365
394
|
rb_funcall(reparented_obj, id_decorate_bang, 0);
|
366
395
|
|
396
|
+
/* if we've created a cycle, raise an exception */
|
397
|
+
raise_if_ancestor_of_self(reparented);
|
398
|
+
|
399
|
+
relink_namespace(reparented);
|
400
|
+
|
367
401
|
return reparented_obj ;
|
368
402
|
}
|
369
403
|
|
404
|
+
// :startdoc:
|
370
405
|
|
371
406
|
/*
|
372
|
-
* call-seq:
|
373
|
-
*
|
407
|
+
* :call-seq:
|
408
|
+
* add_namespace_definition(prefix, href) → Nokogiri::XML::Namespace
|
409
|
+
* add_namespace(prefix, href) → Nokogiri::XML::Namespace
|
410
|
+
*
|
411
|
+
* :category: Manipulating Document Structure
|
412
|
+
*
|
413
|
+
* Adds a namespace definition to this node with +prefix+ using +href+ value, as if this node had
|
414
|
+
* included an attribute "xmlns:prefix=href".
|
415
|
+
*
|
416
|
+
* A default namespace definition for this node can be added by passing +nil+ for +prefix+.
|
417
|
+
*
|
418
|
+
* [Parameters]
|
419
|
+
* - +prefix+ (String, +nil+) An {XML Name}[https://www.w3.org/TR/xml-names/#ns-decl]
|
420
|
+
* - +href+ (String) The {URI reference}[https://www.w3.org/TR/xml-names/#sec-namespaces]
|
421
|
+
*
|
422
|
+
* [Returns] The new Nokogiri::XML::Namespace
|
423
|
+
*
|
424
|
+
* *Example:* adding a non-default namespace definition
|
425
|
+
*
|
426
|
+
* doc = Nokogiri::XML("<store><inventory></inventory></store>")
|
427
|
+
* inventory = doc.at_css("inventory")
|
428
|
+
* inventory.add_namespace_definition("automobile", "http://alices-autos.com/")
|
429
|
+
* inventory.add_namespace_definition("bicycle", "http://bobs-bikes.com/")
|
430
|
+
* inventory.add_child("<automobile:tire>Michelin model XGV, size 75R</automobile:tire>")
|
431
|
+
* doc.to_xml
|
432
|
+
* # => "<?xml version=\"1.0\"?>\n" +
|
433
|
+
* # "<store>\n" +
|
434
|
+
* # " <inventory xmlns:automobile=\"http://alices-autos.com/\" xmlns:bicycle=\"http://bobs-bikes.com/\">\n" +
|
435
|
+
* # " <automobile:tire>Michelin model XGV, size 75R</automobile:tire>\n" +
|
436
|
+
* # " </inventory>\n" +
|
437
|
+
* # "</store>\n"
|
438
|
+
*
|
439
|
+
* *Example:* adding a default namespace definition
|
440
|
+
*
|
441
|
+
* doc = Nokogiri::XML("<store><inventory><tire>Michelin model XGV, size 75R</tire></inventory></store>")
|
442
|
+
* doc.at_css("tire").add_namespace_definition(nil, "http://bobs-bikes.com/")
|
443
|
+
* doc.to_xml
|
444
|
+
* # => "<?xml version=\"1.0\"?>\n" +
|
445
|
+
* # "<store>\n" +
|
446
|
+
* # " <inventory>\n" +
|
447
|
+
* # " <tire xmlns=\"http://bobs-bikes.com/\">Michelin model XGV, size 75R</tire>\n" +
|
448
|
+
* # " </inventory>\n" +
|
449
|
+
* # "</store>\n"
|
374
450
|
*
|
375
|
-
* Get the document for this Node
|
376
451
|
*/
|
377
452
|
static VALUE
|
378
|
-
|
453
|
+
rb_xml_node_add_namespace_definition(VALUE rb_node, VALUE rb_prefix, VALUE rb_href)
|
454
|
+
{
|
455
|
+
xmlNodePtr c_node, element;
|
456
|
+
xmlNsPtr c_namespace;
|
457
|
+
const xmlChar *c_prefix = (const xmlChar *)(NIL_P(rb_prefix) ? NULL : StringValueCStr(rb_prefix));
|
458
|
+
|
459
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
460
|
+
element = c_node ;
|
461
|
+
|
462
|
+
c_namespace = xmlSearchNs(c_node->doc, c_node, c_prefix);
|
463
|
+
|
464
|
+
if (!c_namespace) {
|
465
|
+
if (c_node->type != XML_ELEMENT_NODE) {
|
466
|
+
element = c_node->parent;
|
467
|
+
}
|
468
|
+
c_namespace = xmlNewNs(element, (const xmlChar *)StringValueCStr(rb_href), c_prefix);
|
469
|
+
}
|
470
|
+
|
471
|
+
if (!c_namespace) {
|
472
|
+
return Qnil ;
|
473
|
+
}
|
474
|
+
|
475
|
+
if (NIL_P(rb_prefix) || c_node != element) {
|
476
|
+
xmlSetNs(c_node, c_namespace);
|
477
|
+
}
|
478
|
+
|
479
|
+
return noko_xml_namespace_wrap(c_namespace, c_node->doc);
|
480
|
+
}
|
481
|
+
|
482
|
+
|
483
|
+
/*
|
484
|
+
* :call-seq: attribute(name) → Nokogiri::XML::Attr
|
485
|
+
*
|
486
|
+
* :category: Working With Node Attributes
|
487
|
+
*
|
488
|
+
* [Returns] Attribute (Nokogiri::XML::Attr) belonging to this node with name +name+.
|
489
|
+
*
|
490
|
+
* ⚠ Note that attribute namespaces are ignored and only the simple (non-namespace-prefixed) name is
|
491
|
+
* used to find a matching attribute. In case of a simple name collision, only one of the matching
|
492
|
+
* attributes will be returned. In this case, you will need to use #attribute_with_ns.
|
493
|
+
*
|
494
|
+
* *Example:*
|
495
|
+
*
|
496
|
+
* doc = Nokogiri::XML("<root><child size='large' class='big wide tall'/></root>")
|
497
|
+
* child = doc.at_css("child")
|
498
|
+
* child.attribute("size") # => #<Nokogiri::XML::Attr:0x550 name="size" value="large">
|
499
|
+
* child.attribute("class") # => #<Nokogiri::XML::Attr:0x564 name="class" value="big wide tall">
|
500
|
+
*
|
501
|
+
* *Example* showing that namespaced attributes will not be returned:
|
502
|
+
*
|
503
|
+
* ⚠ Note that only one of the two matching attributes is returned.
|
504
|
+
*
|
505
|
+
* doc = Nokogiri::XML(<<~EOF)
|
506
|
+
* <root xmlns:width='http://example.com/widths'
|
507
|
+
* xmlns:height='http://example.com/heights'>
|
508
|
+
* <child width:size='broad' height:size='tall'/>
|
509
|
+
* </root>
|
510
|
+
* EOF
|
511
|
+
* doc.at_css("child").attribute("size")
|
512
|
+
* # => #(Attr:0x550 {
|
513
|
+
* # name = "size",
|
514
|
+
* # namespace = #(Namespace:0x564 {
|
515
|
+
* # prefix = "width",
|
516
|
+
* # href = "http://example.com/widths"
|
517
|
+
* # }),
|
518
|
+
* # value = "broad"
|
519
|
+
* # })
|
520
|
+
*/
|
521
|
+
static VALUE
|
522
|
+
rb_xml_node_attribute(VALUE self, VALUE name)
|
523
|
+
{
|
524
|
+
xmlNodePtr node;
|
525
|
+
xmlAttrPtr prop;
|
526
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
527
|
+
prop = xmlHasProp(node, (xmlChar *)StringValueCStr(name));
|
528
|
+
|
529
|
+
if (! prop) { return Qnil; }
|
530
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
|
531
|
+
}
|
532
|
+
|
533
|
+
|
534
|
+
/*
|
535
|
+
* :call-seq: attribute_nodes() → Array<Nokogiri::XML::Attr>
|
536
|
+
*
|
537
|
+
* :category: Working With Node Attributes
|
538
|
+
*
|
539
|
+
* [Returns] Attributes (an Array of Nokogiri::XML::Attr) belonging to this node.
|
540
|
+
*
|
541
|
+
* Note that this is the preferred alternative to #attributes when the simple
|
542
|
+
* (non-namespace-prefixed) attribute names may collide.
|
543
|
+
*
|
544
|
+
* *Example:*
|
545
|
+
*
|
546
|
+
* Contrast this with the colliding-name example from #attributes.
|
547
|
+
*
|
548
|
+
* doc = Nokogiri::XML(<<~EOF)
|
549
|
+
* <root xmlns:width='http://example.com/widths'
|
550
|
+
* xmlns:height='http://example.com/heights'>
|
551
|
+
* <child width:size='broad' height:size='tall'/>
|
552
|
+
* </root>
|
553
|
+
* EOF
|
554
|
+
* doc.at_css("child").attribute_nodes
|
555
|
+
* # => [#(Attr:0x550 {
|
556
|
+
* # name = "size",
|
557
|
+
* # namespace = #(Namespace:0x564 {
|
558
|
+
* # prefix = "width",
|
559
|
+
* # href = "http://example.com/widths"
|
560
|
+
* # }),
|
561
|
+
* # value = "broad"
|
562
|
+
* # }),
|
563
|
+
* # #(Attr:0x578 {
|
564
|
+
* # name = "size",
|
565
|
+
* # namespace = #(Namespace:0x58c {
|
566
|
+
* # prefix = "height",
|
567
|
+
* # href = "http://example.com/heights"
|
568
|
+
* # }),
|
569
|
+
* # value = "tall"
|
570
|
+
* # })]
|
571
|
+
*/
|
572
|
+
static VALUE
|
573
|
+
rb_xml_node_attribute_nodes(VALUE rb_node)
|
574
|
+
{
|
575
|
+
xmlNodePtr c_node;
|
576
|
+
|
577
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
578
|
+
|
579
|
+
return noko_xml_node_attrs(c_node);
|
580
|
+
}
|
581
|
+
|
582
|
+
|
583
|
+
/*
|
584
|
+
* :call-seq: attribute_with_ns(name, namespace) → Nokogiri::XML::Attr
|
585
|
+
*
|
586
|
+
* :category: Working With Node Attributes
|
587
|
+
*
|
588
|
+
* [Returns]
|
589
|
+
* Attribute (Nokogiri::XML::Attr) belonging to this node with matching +name+ and +namespace+.
|
590
|
+
*
|
591
|
+
* [Parameters]
|
592
|
+
* - +name+ (String): the simple (non-namespace-prefixed) name of the attribute
|
593
|
+
* - +namespace+ (String): the URI of the attribute's namespace
|
594
|
+
*
|
595
|
+
* See related: #attribute
|
596
|
+
*
|
597
|
+
* *Example:*
|
598
|
+
*
|
599
|
+
* doc = Nokogiri::XML(<<~EOF)
|
600
|
+
* <root xmlns:width='http://example.com/widths'
|
601
|
+
* xmlns:height='http://example.com/heights'>
|
602
|
+
* <child width:size='broad' height:size='tall'/>
|
603
|
+
* </root>
|
604
|
+
* EOF
|
605
|
+
* doc.at_css("child").attribute_with_ns("size", "http://example.com/widths")
|
606
|
+
* # => #(Attr:0x550 {
|
607
|
+
* # name = "size",
|
608
|
+
* # namespace = #(Namespace:0x564 {
|
609
|
+
* # prefix = "width",
|
610
|
+
* # href = "http://example.com/widths"
|
611
|
+
* # }),
|
612
|
+
* # value = "broad"
|
613
|
+
* # })
|
614
|
+
* doc.at_css("child").attribute_with_ns("size", "http://example.com/heights")
|
615
|
+
* # => #(Attr:0x578 {
|
616
|
+
* # name = "size",
|
617
|
+
* # namespace = #(Namespace:0x58c {
|
618
|
+
* # prefix = "height",
|
619
|
+
* # href = "http://example.com/heights"
|
620
|
+
* # }),
|
621
|
+
* # value = "tall"
|
622
|
+
* # })
|
623
|
+
*/
|
624
|
+
static VALUE
|
625
|
+
rb_xml_node_attribute_with_ns(VALUE self, VALUE name, VALUE namespace)
|
379
626
|
{
|
380
627
|
xmlNodePtr node;
|
381
|
-
|
628
|
+
xmlAttrPtr prop;
|
629
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
630
|
+
prop = xmlHasNsProp(node, (xmlChar *)StringValueCStr(name),
|
631
|
+
NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace));
|
632
|
+
|
633
|
+
if (! prop) { return Qnil; }
|
634
|
+
return noko_xml_node_wrap(Qnil, (xmlNodePtr)prop);
|
635
|
+
}
|
636
|
+
|
637
|
+
|
638
|
+
|
639
|
+
/*
|
640
|
+
* call-seq: blank? → Boolean
|
641
|
+
*
|
642
|
+
* [Returns] +true+ if the node is an empty or whitespace-only text or cdata node, else +false+.
|
643
|
+
*
|
644
|
+
* *Example:*
|
645
|
+
*
|
646
|
+
* Nokogiri("<root><child/></root>").root.child.blank? # => false
|
647
|
+
* Nokogiri("<root>\t \n</root>").root.child.blank? # => true
|
648
|
+
* Nokogiri("<root><![CDATA[\t \n]]></root>").root.child.blank? # => true
|
649
|
+
* Nokogiri("<root>not-blank</root>").root.child
|
650
|
+
* .tap { |n| n.content = "" }.blank # => true
|
651
|
+
*/
|
652
|
+
static VALUE
|
653
|
+
rb_xml_node_blank_eh(VALUE self)
|
654
|
+
{
|
655
|
+
xmlNodePtr node;
|
656
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
657
|
+
return (1 == xmlIsBlankNode(node)) ? Qtrue : Qfalse ;
|
658
|
+
}
|
659
|
+
|
660
|
+
|
661
|
+
/*
|
662
|
+
* :call-seq: child() → Nokogiri::XML::Node
|
663
|
+
*
|
664
|
+
* :category: Traversing Document Structure
|
665
|
+
*
|
666
|
+
* [Returns] First of this node's children, or +nil+ if there are no children
|
667
|
+
*
|
668
|
+
* This is a convenience method and is equivalent to:
|
669
|
+
*
|
670
|
+
* node.children.first
|
671
|
+
*
|
672
|
+
* See related: #children
|
673
|
+
*/
|
674
|
+
static VALUE
|
675
|
+
rb_xml_node_child(VALUE self)
|
676
|
+
{
|
677
|
+
xmlNodePtr node, child;
|
678
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
679
|
+
|
680
|
+
child = node->children;
|
681
|
+
if (!child) { return Qnil; }
|
682
|
+
|
683
|
+
return noko_xml_node_wrap(Qnil, child);
|
684
|
+
}
|
685
|
+
|
686
|
+
|
687
|
+
/*
|
688
|
+
* :call-seq: children() → Nokogiri::XML::NodeSet
|
689
|
+
*
|
690
|
+
* :category: Traversing Document Structure
|
691
|
+
*
|
692
|
+
* [Returns] Nokogiri::XML::NodeSet containing this node's children.
|
693
|
+
*/
|
694
|
+
static VALUE
|
695
|
+
rb_xml_node_children(VALUE self)
|
696
|
+
{
|
697
|
+
xmlNodePtr node;
|
698
|
+
xmlNodePtr child;
|
699
|
+
xmlNodeSetPtr set;
|
700
|
+
VALUE document;
|
701
|
+
VALUE node_set;
|
702
|
+
|
703
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
704
|
+
|
705
|
+
child = node->children;
|
706
|
+
set = xmlXPathNodeSetCreate(child);
|
707
|
+
|
708
|
+
document = DOC_RUBY_OBJECT(node->doc);
|
709
|
+
|
710
|
+
if (!child) { return noko_xml_node_set_wrap(set, document); }
|
711
|
+
|
712
|
+
child = child->next;
|
713
|
+
while (NULL != child) {
|
714
|
+
xmlXPathNodeSetAddUnique(set, child);
|
715
|
+
child = child->next;
|
716
|
+
}
|
717
|
+
|
718
|
+
node_set = noko_xml_node_set_wrap(set, document);
|
719
|
+
|
720
|
+
return node_set;
|
721
|
+
}
|
722
|
+
|
723
|
+
|
724
|
+
/*
|
725
|
+
* :call-seq:
|
726
|
+
* content() → String
|
727
|
+
* inner_text() → String
|
728
|
+
* text() → String
|
729
|
+
* to_str() → String
|
730
|
+
*
|
731
|
+
* [Returns]
|
732
|
+
* Contents of all the text nodes in this node's subtree, concatenated together into a single
|
733
|
+
* String.
|
734
|
+
*
|
735
|
+
* ⚠ Note that entities will _always_ be expanded in the returned String.
|
736
|
+
*
|
737
|
+
* See related: #inner_html
|
738
|
+
*
|
739
|
+
* *Example* of how entities are handled:
|
740
|
+
*
|
741
|
+
* Note that <tt><</tt> becomes <tt><</tt> in the returned String.
|
742
|
+
*
|
743
|
+
* doc = Nokogiri::XML.fragment("<child>a < b</child>")
|
744
|
+
* doc.at_css("child").content
|
745
|
+
* # => "a < b"
|
746
|
+
*
|
747
|
+
* *Example* of how a subtree is handled:
|
748
|
+
*
|
749
|
+
* Note that the <tt><span></tt> tags are omitted and only the text node contents are returned,
|
750
|
+
* concatenated into a single string.
|
751
|
+
*
|
752
|
+
* doc = Nokogiri::XML.fragment("<child><span>first</span> <span>second</span></child>")
|
753
|
+
* doc.at_css("child").content
|
754
|
+
* # => "first second"
|
755
|
+
*/
|
756
|
+
static VALUE
|
757
|
+
rb_xml_node_content(VALUE self)
|
758
|
+
{
|
759
|
+
xmlNodePtr node;
|
760
|
+
xmlChar *content;
|
761
|
+
|
762
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
763
|
+
|
764
|
+
content = xmlNodeGetContent(node);
|
765
|
+
if (content) {
|
766
|
+
VALUE rval = NOKOGIRI_STR_NEW2(content);
|
767
|
+
xmlFree(content);
|
768
|
+
return rval;
|
769
|
+
}
|
770
|
+
return Qnil;
|
771
|
+
}
|
772
|
+
|
773
|
+
|
774
|
+
/*
|
775
|
+
* :call-seq: document() → Nokogiri::XML::Document
|
776
|
+
*
|
777
|
+
* :category: Traversing Document Structure
|
778
|
+
*
|
779
|
+
* [Returns] Parent Nokogiri::XML::Document for this node
|
780
|
+
*/
|
781
|
+
static VALUE
|
782
|
+
rb_xml_node_document(VALUE self)
|
783
|
+
{
|
784
|
+
xmlNodePtr node;
|
785
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
382
786
|
return DOC_RUBY_OBJECT(node->doc);
|
383
787
|
}
|
384
788
|
|
385
789
|
/*
|
386
|
-
* call-seq:
|
387
|
-
* pointer_id
|
790
|
+
* :call-seq: pointer_id() → Integer
|
388
791
|
*
|
389
|
-
*
|
792
|
+
* [Returns]
|
793
|
+
* A unique id for this node based on the internal memory structures. This method is used by #==
|
794
|
+
* to determine node identity.
|
390
795
|
*/
|
391
796
|
static VALUE
|
392
|
-
|
797
|
+
rb_xml_node_pointer_id(VALUE self)
|
393
798
|
{
|
394
799
|
xmlNodePtr node;
|
395
|
-
|
800
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
396
801
|
|
397
|
-
return
|
802
|
+
return rb_uint2inum((uintptr_t)(node));
|
398
803
|
}
|
399
804
|
|
400
805
|
/*
|
401
|
-
* call-seq:
|
402
|
-
* encode_special_chars(string)
|
806
|
+
* :call-seq: encode_special_chars(string) → String
|
403
807
|
*
|
404
808
|
* Encode any special characters in +string+
|
405
809
|
*/
|
@@ -410,7 +814,7 @@ encode_special_chars(VALUE self, VALUE string)
|
|
410
814
|
xmlChar *encoded;
|
411
815
|
VALUE encoded_str;
|
412
816
|
|
413
|
-
|
817
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
414
818
|
encoded = xmlEncodeSpecialChars(
|
415
819
|
node->doc,
|
416
820
|
(const xmlChar *)StringValueCStr(string)
|
@@ -423,8 +827,8 @@ encode_special_chars(VALUE self, VALUE string)
|
|
423
827
|
}
|
424
828
|
|
425
829
|
/*
|
426
|
-
* call-seq:
|
427
|
-
*
|
830
|
+
* :call-seq:
|
831
|
+
* create_internal_subset(name, external_id, system_id)
|
428
832
|
*
|
429
833
|
* Create the internal subset of a document.
|
430
834
|
*
|
@@ -441,7 +845,7 @@ create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
|
|
441
845
|
xmlDocPtr doc;
|
442
846
|
xmlDtdPtr dtd;
|
443
847
|
|
444
|
-
|
848
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
445
849
|
|
446
850
|
doc = node->doc;
|
447
851
|
|
@@ -462,8 +866,8 @@ create_internal_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
|
|
462
866
|
}
|
463
867
|
|
464
868
|
/*
|
465
|
-
* call-seq:
|
466
|
-
*
|
869
|
+
* :call-seq:
|
870
|
+
* create_external_subset(name, external_id, system_id)
|
467
871
|
*
|
468
872
|
* Create an external subset
|
469
873
|
*/
|
@@ -474,7 +878,7 @@ create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
|
|
474
878
|
xmlDocPtr doc;
|
475
879
|
xmlDtdPtr dtd;
|
476
880
|
|
477
|
-
|
881
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
478
882
|
|
479
883
|
doc = node->doc;
|
480
884
|
|
@@ -495,8 +899,8 @@ create_external_subset(VALUE self, VALUE name, VALUE external_id, VALUE system_i
|
|
495
899
|
}
|
496
900
|
|
497
901
|
/*
|
498
|
-
* call-seq:
|
499
|
-
*
|
902
|
+
* :call-seq:
|
903
|
+
* external_subset()
|
500
904
|
*
|
501
905
|
* Get the external subset
|
502
906
|
*/
|
@@ -507,7 +911,7 @@ external_subset(VALUE self)
|
|
507
911
|
xmlDocPtr doc;
|
508
912
|
xmlDtdPtr dtd;
|
509
913
|
|
510
|
-
|
914
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
511
915
|
|
512
916
|
if (!node->doc) { return Qnil; }
|
513
917
|
|
@@ -520,8 +924,8 @@ external_subset(VALUE self)
|
|
520
924
|
}
|
521
925
|
|
522
926
|
/*
|
523
|
-
* call-seq:
|
524
|
-
*
|
927
|
+
* :call-seq:
|
928
|
+
* internal_subset()
|
525
929
|
*
|
526
930
|
* Get the internal subset
|
527
931
|
*/
|
@@ -532,7 +936,7 @@ internal_subset(VALUE self)
|
|
532
936
|
xmlDocPtr doc;
|
533
937
|
xmlDtdPtr dtd;
|
534
938
|
|
535
|
-
|
939
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
536
940
|
|
537
941
|
if (!node->doc) { return Qnil; }
|
538
942
|
|
@@ -545,16 +949,19 @@ internal_subset(VALUE self)
|
|
545
949
|
}
|
546
950
|
|
547
951
|
/*
|
548
|
-
* call-seq:
|
549
|
-
*
|
550
|
-
*
|
551
|
-
*
|
952
|
+
* :call-seq:
|
953
|
+
* dup → Nokogiri::XML::Node
|
954
|
+
* dup(depth) → Nokogiri::XML::Node
|
955
|
+
* dup(depth, new_parent_doc) → Nokogiri::XML::Node
|
552
956
|
*
|
553
957
|
* Copy this node.
|
554
|
-
*
|
555
|
-
*
|
556
|
-
*
|
557
|
-
*
|
958
|
+
*
|
959
|
+
* [Parameters]
|
960
|
+
* - +depth+ 0 is a shallow copy, 1 (the default) is a deep copy.
|
961
|
+
* - +new_parent_doc+
|
962
|
+
* The new node's parent Document. Defaults to the this node's document.
|
963
|
+
*
|
964
|
+
* [Returns] The new Nokgiri::XML::Node
|
558
965
|
*/
|
559
966
|
static VALUE
|
560
967
|
duplicate_node(int argc, VALUE *argv, VALUE self)
|
@@ -565,7 +972,7 @@ duplicate_node(int argc, VALUE *argv, VALUE self)
|
|
565
972
|
xmlDocPtr new_parent_doc;
|
566
973
|
xmlNodePtr node, dup;
|
567
974
|
|
568
|
-
|
975
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
569
976
|
|
570
977
|
n_args = rb_scan_args(argc, argv, "02", &r_level, &r_new_parent_doc);
|
571
978
|
|
@@ -589,8 +996,8 @@ duplicate_node(int argc, VALUE *argv, VALUE self)
|
|
589
996
|
}
|
590
997
|
|
591
998
|
/*
|
592
|
-
* call-seq:
|
593
|
-
*
|
999
|
+
* :call-seq:
|
1000
|
+
* unlink() → self
|
594
1001
|
*
|
595
1002
|
* Unlink this node from its current context.
|
596
1003
|
*/
|
@@ -598,25 +1005,12 @@ static VALUE
|
|
598
1005
|
unlink_node(VALUE self)
|
599
1006
|
{
|
600
1007
|
xmlNodePtr node;
|
601
|
-
|
1008
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
602
1009
|
xmlUnlinkNode(node);
|
603
1010
|
noko_xml_document_pin_node(node);
|
604
1011
|
return self;
|
605
1012
|
}
|
606
1013
|
|
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
1014
|
|
621
1015
|
/*
|
622
1016
|
* call-seq:
|
@@ -628,7 +1022,7 @@ static VALUE
|
|
628
1022
|
next_sibling(VALUE self)
|
629
1023
|
{
|
630
1024
|
xmlNodePtr node, sibling;
|
631
|
-
|
1025
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
632
1026
|
|
633
1027
|
sibling = node->next;
|
634
1028
|
if (!sibling) { return Qnil; }
|
@@ -646,7 +1040,7 @@ static VALUE
|
|
646
1040
|
previous_sibling(VALUE self)
|
647
1041
|
{
|
648
1042
|
xmlNodePtr node, sibling;
|
649
|
-
|
1043
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
650
1044
|
|
651
1045
|
sibling = node->prev;
|
652
1046
|
if (!sibling) { return Qnil; }
|
@@ -664,7 +1058,7 @@ static VALUE
|
|
664
1058
|
next_element(VALUE self)
|
665
1059
|
{
|
666
1060
|
xmlNodePtr node, sibling;
|
667
|
-
|
1061
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
668
1062
|
|
669
1063
|
sibling = xmlNextElementSibling(node);
|
670
1064
|
if (!sibling) { return Qnil; }
|
@@ -682,7 +1076,7 @@ static VALUE
|
|
682
1076
|
previous_element(VALUE self)
|
683
1077
|
{
|
684
1078
|
xmlNodePtr node, sibling;
|
685
|
-
|
1079
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
686
1080
|
|
687
1081
|
/*
|
688
1082
|
* note that we don't use xmlPreviousElementSibling here because it's buggy pre-2.7.7.
|
@@ -704,60 +1098,34 @@ replace(VALUE self, VALUE new_node)
|
|
704
1098
|
VALUE reparent = reparent_node_with(self, new_node, xmlReplaceNodeWrapper);
|
705
1099
|
|
706
1100
|
xmlNodePtr pivot;
|
707
|
-
|
1101
|
+
Noko_Node_Get_Struct(self, xmlNode, pivot);
|
708
1102
|
noko_xml_document_pin_node(pivot);
|
709
1103
|
|
710
1104
|
return reparent;
|
711
1105
|
}
|
712
1106
|
|
713
1107
|
/*
|
714
|
-
* call-seq:
|
715
|
-
*
|
1108
|
+
* :call-seq:
|
1109
|
+
* element_children() → NodeSet
|
1110
|
+
* elements() → NodeSet
|
716
1111
|
*
|
717
|
-
*
|
718
|
-
|
719
|
-
|
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
|
1112
|
+
* [Returns]
|
1113
|
+
* The node's child elements as a NodeSet. Only children that are elements will be returned, which
|
1114
|
+
* notably excludes Text nodes.
|
751
1115
|
*
|
752
|
-
*
|
753
|
-
* element nodes.
|
1116
|
+
* *Example:*
|
754
1117
|
*
|
755
|
-
*
|
1118
|
+
* Note that #children returns the Text node "hello" while #element_children does not.
|
756
1119
|
*
|
757
|
-
*
|
1120
|
+
* div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
|
1121
|
+
* div.element_children
|
1122
|
+
* # => [#<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]
|
1123
|
+
* div.children
|
1124
|
+
* # => [#<Nokogiri::XML::Text:0x64 "hello">,
|
1125
|
+
* # #<Nokogiri::XML::Element:0x50 name="span" children=[#<Nokogiri::XML::Text:0x3c "world">]>]
|
758
1126
|
*/
|
759
1127
|
static VALUE
|
760
|
-
|
1128
|
+
rb_xml_node_element_children(VALUE self)
|
761
1129
|
{
|
762
1130
|
xmlNodePtr node;
|
763
1131
|
xmlNodePtr child;
|
@@ -765,7 +1133,7 @@ element_children(VALUE self)
|
|
765
1133
|
VALUE document;
|
766
1134
|
VALUE node_set;
|
767
1135
|
|
768
|
-
|
1136
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
769
1137
|
|
770
1138
|
child = xmlFirstElementChild(node);
|
771
1139
|
set = xmlXPathNodeSetCreate(child);
|
@@ -780,44 +1148,31 @@ element_children(VALUE self)
|
|
780
1148
|
child = xmlNextElementSibling(child);
|
781
1149
|
}
|
782
1150
|
|
783
|
-
node_set = noko_xml_node_set_wrap(set, document);
|
784
|
-
|
785
|
-
return node_set;
|
786
|
-
}
|
787
|
-
|
788
|
-
/*
|
789
|
-
* call-seq:
|
790
|
-
* child
|
791
|
-
*
|
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; }
|
1151
|
+
node_set = noko_xml_node_set_wrap(set, document);
|
802
1152
|
|
803
|
-
return
|
1153
|
+
return node_set;
|
804
1154
|
}
|
805
1155
|
|
806
1156
|
/*
|
807
|
-
* call-seq:
|
808
|
-
*
|
1157
|
+
* :call-seq:
|
1158
|
+
* first_element_child() → Node
|
809
1159
|
*
|
810
|
-
* Returns
|
1160
|
+
* [Returns] The first child Node that is an element.
|
811
1161
|
*
|
812
|
-
* Example
|
1162
|
+
* *Example:*
|
813
1163
|
*
|
814
|
-
*
|
1164
|
+
* Note that the "hello" child, which is a Text node, is skipped and the <tt><span></tt> element is
|
1165
|
+
* returned.
|
1166
|
+
*
|
1167
|
+
* div = Nokogiri::HTML5("<div>hello<span>world</span>").at_css("div")
|
1168
|
+
* div.first_element_child
|
1169
|
+
* # => #(Element:0x3c { name = "span", children = [ #(Text "world")] })
|
815
1170
|
*/
|
816
1171
|
static VALUE
|
817
|
-
|
1172
|
+
rb_xml_node_first_element_child(VALUE self)
|
818
1173
|
{
|
819
1174
|
xmlNodePtr node, child;
|
820
|
-
|
1175
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
821
1176
|
|
822
1177
|
child = xmlFirstElementChild(node);
|
823
1178
|
if (!child) { return Qnil; }
|
@@ -826,20 +1181,25 @@ first_element_child(VALUE self)
|
|
826
1181
|
}
|
827
1182
|
|
828
1183
|
/*
|
829
|
-
* call-seq:
|
830
|
-
*
|
1184
|
+
* :call-seq:
|
1185
|
+
* last_element_child() → Node
|
831
1186
|
*
|
832
|
-
* Returns
|
1187
|
+
* [Returns] The last child Node that is an element.
|
833
1188
|
*
|
834
|
-
* Example
|
1189
|
+
* *Example:*
|
835
1190
|
*
|
836
|
-
*
|
1191
|
+
* Note that the "hello" child, which is a Text node, is skipped and the <tt><span>yes</span></tt>
|
1192
|
+
* element is returned.
|
1193
|
+
*
|
1194
|
+
* div = Nokogiri::HTML5("<div><span>no</span><span>yes</span>skip</div>").at_css("div")
|
1195
|
+
* div.last_element_child
|
1196
|
+
* # => #(Element:0x3c { name = "span", children = [ #(Text "yes")] })
|
837
1197
|
*/
|
838
1198
|
static VALUE
|
839
|
-
|
1199
|
+
rb_xml_node_last_element_child(VALUE self)
|
840
1200
|
{
|
841
1201
|
xmlNodePtr node, child;
|
842
|
-
|
1202
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
843
1203
|
|
844
1204
|
child = xmlLastElementChild(node);
|
845
1205
|
if (!child) { return Qnil; }
|
@@ -857,7 +1217,7 @@ static VALUE
|
|
857
1217
|
key_eh(VALUE self, VALUE attribute)
|
858
1218
|
{
|
859
1219
|
xmlNodePtr node;
|
860
|
-
|
1220
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
861
1221
|
if (xmlHasProp(node, (xmlChar *)StringValueCStr(attribute))) {
|
862
1222
|
return Qtrue;
|
863
1223
|
}
|
@@ -874,7 +1234,7 @@ static VALUE
|
|
874
1234
|
namespaced_key_eh(VALUE self, VALUE attribute, VALUE namespace)
|
875
1235
|
{
|
876
1236
|
xmlNodePtr node;
|
877
|
-
|
1237
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
878
1238
|
if (xmlHasNsProp(node, (xmlChar *)StringValueCStr(attribute),
|
879
1239
|
NIL_P(namespace) ? NULL : (xmlChar *)StringValueCStr(namespace))) {
|
880
1240
|
return Qtrue;
|
@@ -893,7 +1253,7 @@ set(VALUE self, VALUE property, VALUE value)
|
|
893
1253
|
{
|
894
1254
|
xmlNodePtr node, cur;
|
895
1255
|
xmlAttrPtr prop;
|
896
|
-
|
1256
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
897
1257
|
|
898
1258
|
/* If a matching attribute node already exists, then xmlSetProp will destroy
|
899
1259
|
* the existing node's children. However, if Nokogiri has a node object
|
@@ -938,7 +1298,7 @@ get(VALUE self, VALUE rattribute)
|
|
938
1298
|
|
939
1299
|
if (NIL_P(rattribute)) { return Qnil; }
|
940
1300
|
|
941
|
-
|
1301
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
942
1302
|
attribute = xmlCharStrdup(StringValueCStr(rattribute));
|
943
1303
|
|
944
1304
|
colon = DISCARD_CONST_QUAL_XMLCHAR(xmlStrchr(attribute, (const xmlChar)':'));
|
@@ -980,10 +1340,10 @@ set_namespace(VALUE self, VALUE namespace)
|
|
980
1340
|
xmlNodePtr node;
|
981
1341
|
xmlNsPtr ns = NULL;
|
982
1342
|
|
983
|
-
|
1343
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
984
1344
|
|
985
1345
|
if (!NIL_P(namespace)) {
|
986
|
-
|
1346
|
+
Noko_Namespace_Get_Struct(namespace, xmlNs, ns);
|
987
1347
|
}
|
988
1348
|
|
989
1349
|
xmlSetNs(node, ns);
|
@@ -992,70 +1352,32 @@ set_namespace(VALUE self, VALUE namespace)
|
|
992
1352
|
}
|
993
1353
|
|
994
1354
|
/*
|
995
|
-
* call-seq:
|
996
|
-
*
|
1355
|
+
* :call-seq:
|
1356
|
+
* namespace() → Namespace
|
997
1357
|
*
|
998
|
-
*
|
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)
|
1358
|
+
* [Returns] The Namespace of the element or attribute node, or +nil+ if there is no namespace.
|
1015
1359
|
*
|
1016
|
-
*
|
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()
|
1360
|
+
* *Example:*
|
1050
1361
|
*
|
1051
|
-
*
|
1052
|
-
*
|
1362
|
+
* doc = Nokogiri::XML(<<~EOF)
|
1363
|
+
* <root>
|
1364
|
+
* <first/>
|
1365
|
+
* <second xmlns="http://example.com/child"/>
|
1366
|
+
* <foo:third xmlns:foo="http://example.com/foo"/>
|
1367
|
+
* </root>
|
1368
|
+
* EOF
|
1369
|
+
* doc.at_xpath("//first").namespace
|
1370
|
+
* # => nil
|
1371
|
+
* doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace
|
1372
|
+
* # => #(Namespace:0x3c { href = "http://example.com/child" })
|
1373
|
+
* doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace
|
1374
|
+
* # => #(Namespace:0x50 { prefix = "foo", href = "http://example.com/foo" })
|
1053
1375
|
*/
|
1054
1376
|
static VALUE
|
1055
|
-
|
1377
|
+
rb_xml_node_namespace(VALUE rb_node)
|
1056
1378
|
{
|
1057
1379
|
xmlNodePtr c_node ;
|
1058
|
-
|
1380
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1059
1381
|
|
1060
1382
|
if (c_node->ns) {
|
1061
1383
|
return noko_xml_namespace_wrap(c_node->ns, c_node->doc);
|
@@ -1065,10 +1387,32 @@ noko_xml_node_namespace(VALUE rb_node)
|
|
1065
1387
|
}
|
1066
1388
|
|
1067
1389
|
/*
|
1068
|
-
*
|
1069
|
-
*
|
1390
|
+
* :call-seq:
|
1391
|
+
* namespace_definitions() → Array<Nokogiri::XML::Namespace>
|
1392
|
+
*
|
1393
|
+
* [Returns]
|
1394
|
+
* Namespaces that are defined directly on this node, as an Array of Namespace objects. The array
|
1395
|
+
* will be empty if no namespaces are defined on this node.
|
1070
1396
|
*
|
1071
|
-
*
|
1397
|
+
* *Example:*
|
1398
|
+
*
|
1399
|
+
* doc = Nokogiri::XML(<<~EOF)
|
1400
|
+
* <root xmlns="http://example.com/root">
|
1401
|
+
* <first/>
|
1402
|
+
* <second xmlns="http://example.com/child" xmlns:unused="http://example.com/unused"/>
|
1403
|
+
* <foo:third xmlns:foo="http://example.com/foo"/>
|
1404
|
+
* </root>
|
1405
|
+
* EOF
|
1406
|
+
* doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_definitions
|
1407
|
+
* # => []
|
1408
|
+
* doc.at_xpath("//xmlns:second", "xmlns" => "http://example.com/child").namespace_definitions
|
1409
|
+
* # => [#(Namespace:0x3c { href = "http://example.com/child" }),
|
1410
|
+
* # #(Namespace:0x50 {
|
1411
|
+
* # prefix = "unused",
|
1412
|
+
* # href = "http://example.com/unused"
|
1413
|
+
* # })]
|
1414
|
+
* doc.at_xpath("//foo:third", "foo" => "http://example.com/foo").namespace_definitions
|
1415
|
+
* # => [#(Namespace:0x64 { prefix = "foo", href = "http://example.com/foo" })]
|
1072
1416
|
*/
|
1073
1417
|
static VALUE
|
1074
1418
|
namespace_definitions(VALUE rb_node)
|
@@ -1078,7 +1422,7 @@ namespace_definitions(VALUE rb_node)
|
|
1078
1422
|
xmlNsPtr c_namespace;
|
1079
1423
|
VALUE definitions = rb_ary_new();
|
1080
1424
|
|
1081
|
-
|
1425
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1082
1426
|
|
1083
1427
|
c_namespace = c_node->nsDef;
|
1084
1428
|
if (!c_namespace) {
|
@@ -1094,23 +1438,42 @@ namespace_definitions(VALUE rb_node)
|
|
1094
1438
|
}
|
1095
1439
|
|
1096
1440
|
/*
|
1097
|
-
*
|
1098
|
-
*
|
1441
|
+
* :call-seq:
|
1442
|
+
* namespace_scopes() → Array<Nokogiri::XML::Namespace>
|
1443
|
+
*
|
1444
|
+
* [Returns] Array of all the Namespaces on this node and its ancestors.
|
1099
1445
|
*
|
1100
|
-
*
|
1101
|
-
*
|
1102
|
-
*
|
1103
|
-
*
|
1446
|
+
* See also #namespaces
|
1447
|
+
*
|
1448
|
+
* *Example:*
|
1449
|
+
*
|
1450
|
+
* doc = Nokogiri::XML(<<~EOF)
|
1451
|
+
* <root xmlns="http://example.com/root" xmlns:bar="http://example.com/bar">
|
1452
|
+
* <first/>
|
1453
|
+
* <second xmlns="http://example.com/child"/>
|
1454
|
+
* <third xmlns:foo="http://example.com/foo"/>
|
1455
|
+
* </root>
|
1456
|
+
* EOF
|
1457
|
+
* doc.at_xpath("//root:first", "root" => "http://example.com/root").namespace_scopes
|
1458
|
+
* # => [#(Namespace:0x3c { href = "http://example.com/root" }),
|
1459
|
+
* # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
|
1460
|
+
* doc.at_xpath("//child:second", "child" => "http://example.com/child").namespace_scopes
|
1461
|
+
* # => [#(Namespace:0x64 { href = "http://example.com/child" }),
|
1462
|
+
* # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
|
1463
|
+
* doc.at_xpath("//root:third", "root" => "http://example.com/root").namespace_scopes
|
1464
|
+
* # => [#(Namespace:0x78 { prefix = "foo", href = "http://example.com/foo" }),
|
1465
|
+
* # #(Namespace:0x3c { href = "http://example.com/root" }),
|
1466
|
+
* # #(Namespace:0x50 { prefix = "bar", href = "http://example.com/bar" })]
|
1104
1467
|
*/
|
1105
1468
|
static VALUE
|
1106
|
-
|
1469
|
+
rb_xml_node_namespace_scopes(VALUE rb_node)
|
1107
1470
|
{
|
1108
1471
|
xmlNodePtr c_node ;
|
1109
1472
|
xmlNsPtr *namespaces;
|
1110
1473
|
VALUE scopes = rb_ary_new();
|
1111
1474
|
int j;
|
1112
1475
|
|
1113
|
-
|
1476
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1114
1477
|
|
1115
1478
|
namespaces = xmlGetNsList(c_node->doc, c_node);
|
1116
1479
|
if (!namespaces) {
|
@@ -1135,8 +1498,8 @@ static VALUE
|
|
1135
1498
|
node_type(VALUE self)
|
1136
1499
|
{
|
1137
1500
|
xmlNodePtr node;
|
1138
|
-
|
1139
|
-
return INT2NUM(
|
1501
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1502
|
+
return INT2NUM(node->type);
|
1140
1503
|
}
|
1141
1504
|
|
1142
1505
|
/*
|
@@ -1149,7 +1512,7 @@ static VALUE
|
|
1149
1512
|
set_native_content(VALUE self, VALUE content)
|
1150
1513
|
{
|
1151
1514
|
xmlNodePtr node, child, next ;
|
1152
|
-
|
1515
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1153
1516
|
|
1154
1517
|
child = node->children;
|
1155
1518
|
while (NULL != child) {
|
@@ -1163,30 +1526,6 @@ set_native_content(VALUE self, VALUE content)
|
|
1163
1526
|
return content;
|
1164
1527
|
}
|
1165
1528
|
|
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
1529
|
/*
|
1191
1530
|
* call-seq:
|
1192
1531
|
* lang=
|
@@ -1199,7 +1538,7 @@ set_lang(VALUE self_rb, VALUE lang_rb)
|
|
1199
1538
|
xmlNodePtr self ;
|
1200
1539
|
xmlChar *lang ;
|
1201
1540
|
|
1202
|
-
|
1541
|
+
Noko_Node_Get_Struct(self_rb, xmlNode, self);
|
1203
1542
|
lang = (xmlChar *)StringValueCStr(lang_rb);
|
1204
1543
|
|
1205
1544
|
xmlNodeSetLang(self, lang);
|
@@ -1221,7 +1560,7 @@ get_lang(VALUE self_rb)
|
|
1221
1560
|
xmlChar *lang ;
|
1222
1561
|
VALUE lang_rb ;
|
1223
1562
|
|
1224
|
-
|
1563
|
+
Noko_Node_Get_Struct(self_rb, xmlNode, self);
|
1225
1564
|
|
1226
1565
|
lang = xmlNodeGetLang(self);
|
1227
1566
|
if (lang) {
|
@@ -1250,7 +1589,7 @@ static VALUE
|
|
1250
1589
|
get_parent(VALUE self)
|
1251
1590
|
{
|
1252
1591
|
xmlNodePtr node, parent;
|
1253
|
-
|
1592
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1254
1593
|
|
1255
1594
|
parent = node->parent;
|
1256
1595
|
if (!parent) { return Qnil; }
|
@@ -1268,7 +1607,7 @@ static VALUE
|
|
1268
1607
|
set_name(VALUE self, VALUE new_name)
|
1269
1608
|
{
|
1270
1609
|
xmlNodePtr node;
|
1271
|
-
|
1610
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1272
1611
|
xmlNodeSetName(node, (xmlChar *)StringValueCStr(new_name));
|
1273
1612
|
return new_name;
|
1274
1613
|
}
|
@@ -1283,7 +1622,7 @@ static VALUE
|
|
1283
1622
|
get_name(VALUE self)
|
1284
1623
|
{
|
1285
1624
|
xmlNodePtr node;
|
1286
|
-
|
1625
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1287
1626
|
if (node->name) {
|
1288
1627
|
return NOKOGIRI_STR_NEW2(node->name);
|
1289
1628
|
}
|
@@ -1297,13 +1636,13 @@ get_name(VALUE self)
|
|
1297
1636
|
* Returns the path associated with this Node
|
1298
1637
|
*/
|
1299
1638
|
static VALUE
|
1300
|
-
|
1639
|
+
rb_xml_node_path(VALUE rb_node)
|
1301
1640
|
{
|
1302
1641
|
xmlNodePtr c_node;
|
1303
1642
|
xmlChar *c_path ;
|
1304
1643
|
VALUE rval;
|
1305
1644
|
|
1306
|
-
|
1645
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1307
1646
|
|
1308
1647
|
c_path = xmlGetNodePath(c_node);
|
1309
1648
|
if (c_path == NULL) {
|
@@ -1352,7 +1691,7 @@ native_write_to(
|
|
1352
1691
|
const char *before_indent;
|
1353
1692
|
xmlSaveCtxtPtr savectx;
|
1354
1693
|
|
1355
|
-
|
1694
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1356
1695
|
|
1357
1696
|
xmlIndentTreeOutput = 1;
|
1358
1697
|
|
@@ -1375,112 +1714,362 @@ native_write_to(
|
|
1375
1714
|
return io;
|
1376
1715
|
}
|
1377
1716
|
|
1378
|
-
|
1379
|
-
|
1380
|
-
*
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1717
|
+
|
1718
|
+
static inline void
|
1719
|
+
output_partial_string(VALUE out, char const *str, size_t length)
|
1720
|
+
{
|
1721
|
+
if (length) {
|
1722
|
+
rb_enc_str_buf_cat(out, str, (long)length, rb_utf8_encoding());
|
1723
|
+
}
|
1724
|
+
}
|
1725
|
+
|
1726
|
+
static inline void
|
1727
|
+
output_char(VALUE out, char ch)
|
1728
|
+
{
|
1729
|
+
output_partial_string(out, &ch, 1);
|
1730
|
+
}
|
1731
|
+
|
1732
|
+
static inline void
|
1733
|
+
output_string(VALUE out, char const *str)
|
1734
|
+
{
|
1735
|
+
output_partial_string(out, str, strlen(str));
|
1736
|
+
}
|
1737
|
+
|
1738
|
+
static inline void
|
1739
|
+
output_tagname(VALUE out, xmlNodePtr elem)
|
1740
|
+
{
|
1741
|
+
// Elements in the HTML, MathML, and SVG namespaces do not use a namespace
|
1742
|
+
// prefix in the HTML syntax.
|
1743
|
+
char const *name = (char const *)elem->name;
|
1744
|
+
xmlNsPtr ns = elem->ns;
|
1745
|
+
if (ns && ns->href && ns->prefix
|
1746
|
+
&& strcmp((char const *)ns->href, "http://www.w3.org/1999/xhtml")
|
1747
|
+
&& strcmp((char const *)ns->href, "http://www.w3.org/1998/Math/MathML")
|
1748
|
+
&& strcmp((char const *)ns->href, "http://www.w3.org/2000/svg")) {
|
1749
|
+
output_string(out, (char const *)elem->ns->prefix);
|
1750
|
+
output_char(out, ':');
|
1751
|
+
char const *colon = strchr(name, ':');
|
1752
|
+
if (colon) {
|
1753
|
+
name = colon + 1;
|
1754
|
+
}
|
1755
|
+
}
|
1756
|
+
output_string(out, name);
|
1757
|
+
}
|
1758
|
+
|
1759
|
+
static inline void
|
1760
|
+
output_attr_name(VALUE out, xmlAttrPtr attr)
|
1761
|
+
{
|
1762
|
+
xmlNsPtr ns = attr->ns;
|
1763
|
+
char const *name = (char const *)attr->name;
|
1764
|
+
if (ns && ns->href) {
|
1765
|
+
char const *uri = (char const *)ns->href;
|
1766
|
+
char const *localname = strchr(name, ':');
|
1767
|
+
if (localname) {
|
1768
|
+
++localname;
|
1769
|
+
} else {
|
1770
|
+
localname = name;
|
1771
|
+
}
|
1772
|
+
|
1773
|
+
if (!strcmp(uri, "http://www.w3.org/XML/1998/namespace")) {
|
1774
|
+
output_string(out, "xml:");
|
1775
|
+
name = localname;
|
1776
|
+
} else if (!strcmp(uri, "http://www.w3.org/2000/xmlns/")) {
|
1777
|
+
// xmlns:xmlns -> xmlns
|
1778
|
+
// xmlns:foo -> xmlns:foo
|
1779
|
+
if (strcmp(localname, "xmlns")) {
|
1780
|
+
output_string(out, "xmlns:");
|
1781
|
+
}
|
1782
|
+
name = localname;
|
1783
|
+
} else if (!strcmp(uri, "http://www.w3.org/1999/xlink")) {
|
1784
|
+
output_string(out, "xlink:");
|
1785
|
+
name = localname;
|
1786
|
+
} else if (ns->prefix) {
|
1787
|
+
output_string(out, (char const *)ns->prefix);
|
1788
|
+
output_char(out, ':');
|
1789
|
+
name = localname;
|
1790
|
+
}
|
1791
|
+
}
|
1792
|
+
output_string(out, name);
|
1793
|
+
}
|
1794
|
+
|
1795
|
+
static void
|
1796
|
+
output_escaped_string(VALUE out, xmlChar const *start, bool attr)
|
1797
|
+
{
|
1798
|
+
xmlChar const *next = start;
|
1799
|
+
int ch;
|
1800
|
+
|
1801
|
+
while ((ch = *next) != 0) {
|
1802
|
+
char const *replacement = NULL;
|
1803
|
+
size_t replaced_bytes = 1;
|
1804
|
+
if (ch == '&') {
|
1805
|
+
replacement = "&";
|
1806
|
+
} else if (ch == 0xC2 && next[1] == 0xA0) {
|
1807
|
+
// U+00A0 NO-BREAK SPACE has the UTF-8 encoding C2 A0.
|
1808
|
+
replacement = " ";
|
1809
|
+
replaced_bytes = 2;
|
1810
|
+
} else if (attr && ch == '"') {
|
1811
|
+
replacement = """;
|
1812
|
+
} else if (!attr && ch == '<') {
|
1813
|
+
replacement = "<";
|
1814
|
+
} else if (!attr && ch == '>') {
|
1815
|
+
replacement = ">";
|
1816
|
+
} else {
|
1817
|
+
++next;
|
1818
|
+
continue;
|
1819
|
+
}
|
1820
|
+
output_partial_string(out, (char const *)start, next - start);
|
1821
|
+
output_string(out, replacement);
|
1822
|
+
next += replaced_bytes;
|
1823
|
+
start = next;
|
1824
|
+
}
|
1825
|
+
output_partial_string(out, (char const *)start, next - start);
|
1826
|
+
}
|
1827
|
+
|
1828
|
+
static bool
|
1829
|
+
should_prepend_newline(xmlNodePtr node)
|
1830
|
+
{
|
1831
|
+
char const *name = (char const *)node->name;
|
1832
|
+
xmlNodePtr child = node->children;
|
1833
|
+
|
1834
|
+
if (!name || !child || (strcmp(name, "pre") && strcmp(name, "textarea") && strcmp(name, "listing"))) {
|
1835
|
+
return false;
|
1836
|
+
}
|
1837
|
+
|
1838
|
+
return child->type == XML_TEXT_NODE && child->content && child->content[0] == '\n';
|
1839
|
+
}
|
1840
|
+
|
1384
1841
|
static VALUE
|
1385
|
-
|
1842
|
+
rb_prepend_newline(VALUE self)
|
1386
1843
|
{
|
1387
1844
|
xmlNodePtr node;
|
1388
|
-
|
1845
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1846
|
+
return should_prepend_newline(node) ? Qtrue : Qfalse;
|
1847
|
+
}
|
1848
|
+
|
1849
|
+
static bool
|
1850
|
+
is_one_of(xmlNodePtr node, char const *const *tagnames, size_t num_tagnames)
|
1851
|
+
{
|
1852
|
+
char const *name = (char const *)node->name;
|
1853
|
+
if (name == NULL) { // fragments don't have a name
|
1854
|
+
return false;
|
1855
|
+
}
|
1856
|
+
for (size_t idx = 0; idx < num_tagnames; ++idx) {
|
1857
|
+
if (!strcmp(name, tagnames[idx])) {
|
1858
|
+
return true;
|
1859
|
+
}
|
1860
|
+
}
|
1861
|
+
return false;
|
1862
|
+
|
1863
|
+
}
|
1864
|
+
|
1865
|
+
static void
|
1866
|
+
output_node(
|
1867
|
+
VALUE out,
|
1868
|
+
xmlNodePtr node,
|
1869
|
+
bool preserve_newline
|
1870
|
+
)
|
1871
|
+
{
|
1872
|
+
static char const *const VOID_ELEMENTS[] = {
|
1873
|
+
"area", "base", "basefont", "bgsound", "br", "col", "embed", "frame", "hr",
|
1874
|
+
"img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr",
|
1875
|
+
};
|
1876
|
+
|
1877
|
+
static char const *const UNESCAPED_TEXT_ELEMENTS[] = {
|
1878
|
+
"style", "script", "xmp", "iframe", "noembed", "noframes", "plaintext", "noscript",
|
1879
|
+
};
|
1880
|
+
|
1881
|
+
switch (node->type) {
|
1882
|
+
case XML_ELEMENT_NODE:
|
1883
|
+
// Serialize the start tag.
|
1884
|
+
output_char(out, '<');
|
1885
|
+
output_tagname(out, node);
|
1886
|
+
|
1887
|
+
// Add attributes.
|
1888
|
+
for (xmlAttrPtr attr = node->properties; attr; attr = attr->next) {
|
1889
|
+
output_char(out, ' ');
|
1890
|
+
output_attr_name(out, attr);
|
1891
|
+
if (attr->children) {
|
1892
|
+
output_string(out, "=\"");
|
1893
|
+
xmlChar *value = xmlNodeListGetString(attr->doc, attr->children, 1);
|
1894
|
+
output_escaped_string(out, value, true);
|
1895
|
+
xmlFree(value);
|
1896
|
+
output_char(out, '"');
|
1897
|
+
} else {
|
1898
|
+
// Output name=""
|
1899
|
+
output_string(out, "=\"\"");
|
1900
|
+
}
|
1901
|
+
}
|
1902
|
+
output_char(out, '>');
|
1903
|
+
|
1904
|
+
// Add children and end tag if element is not void.
|
1905
|
+
if (!is_one_of(node, VOID_ELEMENTS, sizeof VOID_ELEMENTS / sizeof VOID_ELEMENTS[0])) {
|
1906
|
+
if (preserve_newline && should_prepend_newline(node)) {
|
1907
|
+
output_char(out, '\n');
|
1908
|
+
}
|
1909
|
+
for (xmlNodePtr child = node->children; child; child = child->next) {
|
1910
|
+
output_node(out, child, preserve_newline);
|
1911
|
+
}
|
1912
|
+
output_string(out, "</");
|
1913
|
+
output_tagname(out, node);
|
1914
|
+
output_char(out, '>');
|
1915
|
+
}
|
1916
|
+
break;
|
1917
|
+
|
1918
|
+
case XML_TEXT_NODE:
|
1919
|
+
if (node->parent
|
1920
|
+
&& is_one_of(node->parent, UNESCAPED_TEXT_ELEMENTS,
|
1921
|
+
sizeof UNESCAPED_TEXT_ELEMENTS / sizeof UNESCAPED_TEXT_ELEMENTS[0])) {
|
1922
|
+
output_string(out, (char const *)node->content);
|
1923
|
+
} else {
|
1924
|
+
output_escaped_string(out, node->content, false);
|
1925
|
+
}
|
1926
|
+
break;
|
1927
|
+
|
1928
|
+
case XML_CDATA_SECTION_NODE:
|
1929
|
+
output_string(out, "<![CDATA[");
|
1930
|
+
output_string(out, (char const *)node->content);
|
1931
|
+
output_string(out, "]]>");
|
1932
|
+
break;
|
1933
|
+
|
1934
|
+
case XML_COMMENT_NODE:
|
1935
|
+
output_string(out, "<!--");
|
1936
|
+
output_string(out, (char const *)node->content);
|
1937
|
+
output_string(out, "-->");
|
1938
|
+
break;
|
1939
|
+
|
1940
|
+
case XML_PI_NODE:
|
1941
|
+
output_string(out, "<?");
|
1942
|
+
output_string(out, (char const *)node->content);
|
1943
|
+
output_char(out, '>');
|
1944
|
+
break;
|
1945
|
+
|
1946
|
+
case XML_DOCUMENT_TYPE_NODE:
|
1947
|
+
case XML_DTD_NODE:
|
1948
|
+
output_string(out, "<!DOCTYPE ");
|
1949
|
+
output_string(out, (char const *)node->name);
|
1950
|
+
output_string(out, ">");
|
1951
|
+
break;
|
1952
|
+
|
1953
|
+
case XML_DOCUMENT_NODE:
|
1954
|
+
case XML_DOCUMENT_FRAG_NODE:
|
1955
|
+
case XML_HTML_DOCUMENT_NODE:
|
1956
|
+
for (xmlNodePtr child = node->children; child; child = child->next) {
|
1957
|
+
output_node(out, child, preserve_newline);
|
1958
|
+
}
|
1959
|
+
break;
|
1960
|
+
|
1961
|
+
default:
|
1962
|
+
rb_raise(rb_eRuntimeError, "Unsupported document node (%d); this is a bug in Nokogiri", node->type);
|
1963
|
+
break;
|
1964
|
+
}
|
1965
|
+
}
|
1389
1966
|
|
1390
|
-
|
1967
|
+
static VALUE
|
1968
|
+
html_standard_serialize(
|
1969
|
+
VALUE self,
|
1970
|
+
VALUE preserve_newline
|
1971
|
+
)
|
1972
|
+
{
|
1973
|
+
xmlNodePtr node;
|
1974
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1975
|
+
VALUE output = rb_str_buf_new(4096);
|
1976
|
+
output_node(output, node, RTEST(preserve_newline));
|
1977
|
+
return output;
|
1391
1978
|
}
|
1392
1979
|
|
1393
1980
|
/*
|
1394
|
-
* call-seq:
|
1395
|
-
*
|
1981
|
+
* :call-seq:
|
1982
|
+
* line() → Integer
|
1396
1983
|
*
|
1397
|
-
*
|
1984
|
+
* [Returns] The line number of this Node.
|
1985
|
+
*
|
1986
|
+
* ---
|
1987
|
+
*
|
1988
|
+
* <b> ⚠ The CRuby and JRuby implementations differ in important ways! </b>
|
1989
|
+
*
|
1990
|
+
* Semantic differences:
|
1991
|
+
* - The CRuby method reflects the node's line number <i>in the parsed string</i>
|
1992
|
+
* - The JRuby method reflects the node's line number <i>in the final DOM structure</i> after
|
1993
|
+
* corrections have been applied
|
1994
|
+
*
|
1995
|
+
* Performance differences:
|
1996
|
+
* - The CRuby method is {O(1)}[https://en.wikipedia.org/wiki/Time_complexity#Constant_time]
|
1997
|
+
* (constant time)
|
1998
|
+
* - The JRuby method is {O(n)}[https://en.wikipedia.org/wiki/Time_complexity#Linear_time] (linear
|
1999
|
+
* time, where n is the number of nodes before/above the element in the DOM)
|
2000
|
+
*
|
2001
|
+
* If you'd like to help improve the JRuby implementation, please review these issues and reach out
|
2002
|
+
* to the maintainers:
|
2003
|
+
* - https://github.com/sparklemotion/nokogiri/issues/1223
|
2004
|
+
* - https://github.com/sparklemotion/nokogiri/pull/2177
|
2005
|
+
* - https://github.com/sparklemotion/nokogiri/issues/2380
|
1398
2006
|
*/
|
1399
2007
|
static VALUE
|
1400
|
-
|
2008
|
+
rb_xml_node_line(VALUE rb_node)
|
1401
2009
|
{
|
1402
|
-
xmlNodePtr
|
1403
|
-
|
1404
|
-
|
1405
|
-
Data_Get_Struct(self, xmlNode, node);
|
1406
|
-
if (value < 65535) {
|
1407
|
-
node->line = value;
|
1408
|
-
}
|
2010
|
+
xmlNodePtr c_node;
|
2011
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1409
2012
|
|
1410
|
-
return
|
2013
|
+
return LONG2NUM(xmlGetLineNo(c_node));
|
1411
2014
|
}
|
1412
2015
|
|
1413
2016
|
/*
|
1414
2017
|
* call-seq:
|
1415
|
-
*
|
1416
|
-
*
|
1417
|
-
*
|
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.
|
2018
|
+
* line=(num)
|
2019
|
+
*
|
2020
|
+
* Sets the line for this Node. num must be less than 65535.
|
1423
2021
|
*/
|
1424
2022
|
static VALUE
|
1425
|
-
|
2023
|
+
rb_xml_node_line_set(VALUE rb_node, VALUE rb_line_number)
|
1426
2024
|
{
|
1427
|
-
xmlNodePtr c_node
|
1428
|
-
|
1429
|
-
const xmlChar *c_prefix = (const xmlChar *)(NIL_P(rb_prefix) ? NULL : StringValueCStr(rb_prefix));
|
1430
|
-
|
1431
|
-
Data_Get_Struct(rb_node, xmlNode, c_node);
|
1432
|
-
element = c_node ;
|
2025
|
+
xmlNodePtr c_node;
|
2026
|
+
int line_number = NUM2INT(rb_line_number);
|
1433
2027
|
|
1434
|
-
|
2028
|
+
Noko_Node_Get_Struct(rb_node, xmlNode, c_node);
|
1435
2029
|
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
2030
|
+
// libxml2 optionally uses xmlNode.psvi to store longer line numbers, but only for text nodes.
|
2031
|
+
// search for "psvi" in SAX2.c and tree.c to learn more.
|
2032
|
+
if (line_number < 65535) {
|
2033
|
+
c_node->line = (short) line_number;
|
2034
|
+
} else {
|
2035
|
+
c_node->line = 65535;
|
2036
|
+
if (c_node->type == XML_TEXT_NODE) {
|
2037
|
+
c_node->psvi = (void *)(ptrdiff_t) line_number;
|
1439
2038
|
}
|
1440
|
-
c_namespace = xmlNewNs(element, (const xmlChar *)StringValueCStr(rb_href), c_prefix);
|
1441
|
-
}
|
1442
|
-
|
1443
|
-
if (!c_namespace) {
|
1444
|
-
return Qnil ;
|
1445
|
-
}
|
1446
|
-
|
1447
|
-
if (NIL_P(rb_prefix) || c_node != element) {
|
1448
|
-
xmlSetNs(c_node, c_namespace);
|
1449
2039
|
}
|
1450
2040
|
|
1451
|
-
return
|
2041
|
+
return rb_line_number;
|
1452
2042
|
}
|
1453
2043
|
|
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
|
-
*/
|
2044
|
+
/* :nodoc: documented in lib/nokogiri/xml/node.rb */
|
1463
2045
|
static VALUE
|
1464
2046
|
rb_xml_node_new(int argc, VALUE *argv, VALUE klass)
|
1465
2047
|
{
|
1466
|
-
|
1467
|
-
xmlNodePtr
|
1468
|
-
VALUE
|
1469
|
-
VALUE
|
2048
|
+
xmlNodePtr c_document_node;
|
2049
|
+
xmlNodePtr c_node;
|
2050
|
+
VALUE rb_name;
|
2051
|
+
VALUE rb_document_node;
|
1470
2052
|
VALUE rest;
|
1471
2053
|
VALUE rb_node;
|
1472
2054
|
|
1473
|
-
rb_scan_args(argc, argv, "2*", &
|
2055
|
+
rb_scan_args(argc, argv, "2*", &rb_name, &rb_document_node, &rest);
|
1474
2056
|
|
1475
|
-
|
2057
|
+
if (!rb_obj_is_kind_of(rb_document_node, cNokogiriXmlNode)) {
|
2058
|
+
rb_raise(rb_eArgError, "document must be a Nokogiri::XML::Node");
|
2059
|
+
}
|
2060
|
+
if (!rb_obj_is_kind_of(rb_document_node, cNokogiriXmlDocument)) {
|
2061
|
+
// TODO: deprecate allowing Node
|
2062
|
+
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.");
|
2063
|
+
}
|
2064
|
+
Noko_Node_Get_Struct(rb_document_node, xmlNode, c_document_node);
|
1476
2065
|
|
1477
|
-
|
1478
|
-
|
1479
|
-
noko_xml_document_pin_node(
|
2066
|
+
c_node = xmlNewNode(NULL, (xmlChar *)StringValueCStr(rb_name));
|
2067
|
+
c_node->doc = c_document_node->doc;
|
2068
|
+
noko_xml_document_pin_node(c_node);
|
1480
2069
|
|
1481
2070
|
rb_node = noko_xml_node_wrap(
|
1482
2071
|
klass == cNokogiriXmlNode ? (VALUE)NULL : klass,
|
1483
|
-
|
2072
|
+
c_node
|
1484
2073
|
);
|
1485
2074
|
rb_obj_call_init(rb_node, argc, argv);
|
1486
2075
|
|
@@ -1502,7 +2091,7 @@ dump_html(VALUE self)
|
|
1502
2091
|
xmlNodePtr node ;
|
1503
2092
|
VALUE html;
|
1504
2093
|
|
1505
|
-
|
2094
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1506
2095
|
|
1507
2096
|
buf = xmlBufferCreate() ;
|
1508
2097
|
htmlNodeDump(buf, node->doc, node);
|
@@ -1521,10 +2110,10 @@ static VALUE
|
|
1521
2110
|
compare(VALUE self, VALUE _other)
|
1522
2111
|
{
|
1523
2112
|
xmlNodePtr node, other;
|
1524
|
-
|
1525
|
-
|
2113
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
2114
|
+
Noko_Node_Get_Struct(_other, xmlNode, other);
|
1526
2115
|
|
1527
|
-
return INT2NUM(
|
2116
|
+
return INT2NUM(xmlXPathCmpNodes(other, node));
|
1528
2117
|
}
|
1529
2118
|
|
1530
2119
|
|
@@ -1542,7 +2131,7 @@ process_xincludes(VALUE self, VALUE options)
|
|
1542
2131
|
xmlNodePtr node;
|
1543
2132
|
VALUE error_list = rb_ary_new();
|
1544
2133
|
|
1545
|
-
|
2134
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1546
2135
|
|
1547
2136
|
xmlSetStructuredErrorFunc((void *)error_list, Nokogiri_error_array_pusher);
|
1548
2137
|
rcode = xmlXIncludeProcessTreeFlags(node, (int)NUM2INT(options));
|
@@ -1573,7 +2162,7 @@ in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1573
2162
|
VALUE doc, err;
|
1574
2163
|
int doc_is_empty;
|
1575
2164
|
|
1576
|
-
|
2165
|
+
Noko_Node_Get_Struct(self, xmlNode, node);
|
1577
2166
|
|
1578
2167
|
doc = DOC_RUBY_OBJECT(node->doc);
|
1579
2168
|
err = rb_iv_get(doc, "@errors");
|
@@ -1614,9 +2203,7 @@ in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1614
2203
|
*/
|
1615
2204
|
child_iter = node->doc->children ;
|
1616
2205
|
while (child_iter) {
|
1617
|
-
|
1618
|
-
child_iter->parent = (xmlNodePtr)node->doc;
|
1619
|
-
}
|
2206
|
+
child_iter->parent = (xmlNodePtr)node->doc;
|
1620
2207
|
child_iter = child_iter->next;
|
1621
2208
|
}
|
1622
2209
|
|
@@ -1626,12 +2213,17 @@ in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1626
2213
|
|
1627
2214
|
xmlSetStructuredErrorFunc(NULL, NULL);
|
1628
2215
|
|
1629
|
-
/*
|
2216
|
+
/*
|
2217
|
+
* Workaround for a libxml2 bug where a parsing error may leave a broken
|
1630
2218
|
* node reference in node->doc->children.
|
2219
|
+
*
|
2220
|
+
* https://bugzilla.gnome.org/show_bug.cgi?id=668155
|
2221
|
+
*
|
1631
2222
|
* This workaround is limited to when a parse error occurs, the document
|
1632
2223
|
* went from having no children to having children, and the context node is
|
1633
2224
|
* part of a document fragment.
|
1634
|
-
*
|
2225
|
+
*
|
2226
|
+
* TODO: This was fixed in libxml 2.8.0 by 71a243d
|
1635
2227
|
*/
|
1636
2228
|
if (error != XML_ERR_OK && doc_is_empty && node->doc->children != NULL) {
|
1637
2229
|
child_iter = node;
|
@@ -1667,14 +2259,12 @@ in_context(VALUE self, VALUE _str, VALUE _options)
|
|
1667
2259
|
return noko_xml_node_set_wrap(set, doc);
|
1668
2260
|
}
|
1669
2261
|
|
1670
|
-
|
1671
2262
|
VALUE
|
1672
2263
|
noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
|
1673
2264
|
{
|
1674
2265
|
VALUE rb_document, rb_node_cache, rb_node;
|
1675
2266
|
nokogiriTuplePtr node_has_a_document;
|
1676
2267
|
xmlDocPtr c_doc;
|
1677
|
-
void (*mark_method)(xmlNodePtr) = NULL ;
|
1678
2268
|
|
1679
2269
|
assert(c_node);
|
1680
2270
|
|
@@ -1682,11 +2272,9 @@ noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
|
|
1682
2272
|
return DOC_RUBY_OBJECT(c_node->doc);
|
1683
2273
|
}
|
1684
2274
|
|
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
2275
|
c_doc = c_node->doc;
|
1689
|
-
|
2276
|
+
|
2277
|
+
// Nodes yielded from XML::Reader don't have a fully-realized Document
|
1690
2278
|
node_has_a_document = DOC_RUBY_OBJECT_TEST(c_doc);
|
1691
2279
|
|
1692
2280
|
if (c_node->_private && node_has_a_document) {
|
@@ -1736,9 +2324,7 @@ noko_xml_node_wrap(VALUE rb_class, xmlNodePtr c_node)
|
|
1736
2324
|
}
|
1737
2325
|
}
|
1738
2326
|
|
1739
|
-
|
1740
|
-
|
1741
|
-
rb_node = Data_Wrap_Struct(rb_class, mark_method, debug_node_dealloc, c_node) ;
|
2327
|
+
rb_node = TypedData_Wrap_Struct(rb_class, &nokogiri_node_type, c_node) ;
|
1742
2328
|
c_node->_private = (void *)rb_node;
|
1743
2329
|
|
1744
2330
|
if (node_has_a_document) {
|
@@ -1771,7 +2357,7 @@ noko_xml_node_attrs(xmlNodePtr c_node)
|
|
1771
2357
|
}
|
1772
2358
|
|
1773
2359
|
void
|
1774
|
-
noko_init_xml_node()
|
2360
|
+
noko_init_xml_node(void)
|
1775
2361
|
{
|
1776
2362
|
cNokogiriXmlNode = rb_define_class_under(mNokogiriXml, "Node", rb_cObject);
|
1777
2363
|
|
@@ -1779,61 +2365,61 @@ noko_init_xml_node()
|
|
1779
2365
|
|
1780
2366
|
rb_define_singleton_method(cNokogiriXmlNode, "new", rb_xml_node_new, -1);
|
1781
2367
|
|
1782
|
-
rb_define_method(cNokogiriXmlNode, "add_namespace_definition",
|
2368
|
+
rb_define_method(cNokogiriXmlNode, "add_namespace_definition", rb_xml_node_add_namespace_definition, 2);
|
2369
|
+
rb_define_method(cNokogiriXmlNode, "attribute", rb_xml_node_attribute, 1);
|
2370
|
+
rb_define_method(cNokogiriXmlNode, "attribute_nodes", rb_xml_node_attribute_nodes, 0);
|
2371
|
+
rb_define_method(cNokogiriXmlNode, "attribute_with_ns", rb_xml_node_attribute_with_ns, 2);
|
2372
|
+
rb_define_method(cNokogiriXmlNode, "blank?", rb_xml_node_blank_eh, 0);
|
2373
|
+
rb_define_method(cNokogiriXmlNode, "child", rb_xml_node_child, 0);
|
2374
|
+
rb_define_method(cNokogiriXmlNode, "children", rb_xml_node_children, 0);
|
2375
|
+
rb_define_method(cNokogiriXmlNode, "content", rb_xml_node_content, 0);
|
2376
|
+
rb_define_method(cNokogiriXmlNode, "create_external_subset", create_external_subset, 3);
|
2377
|
+
rb_define_method(cNokogiriXmlNode, "create_internal_subset", create_internal_subset, 3);
|
2378
|
+
rb_define_method(cNokogiriXmlNode, "document", rb_xml_node_document, 0);
|
2379
|
+
rb_define_method(cNokogiriXmlNode, "dup", duplicate_node, -1);
|
2380
|
+
rb_define_method(cNokogiriXmlNode, "element_children", rb_xml_node_element_children, 0);
|
2381
|
+
rb_define_method(cNokogiriXmlNode, "encode_special_chars", encode_special_chars, 1);
|
2382
|
+
rb_define_method(cNokogiriXmlNode, "external_subset", external_subset, 0);
|
2383
|
+
rb_define_method(cNokogiriXmlNode, "first_element_child", rb_xml_node_first_element_child, 0);
|
2384
|
+
rb_define_method(cNokogiriXmlNode, "internal_subset", internal_subset, 0);
|
2385
|
+
rb_define_method(cNokogiriXmlNode, "key?", key_eh, 1);
|
2386
|
+
rb_define_method(cNokogiriXmlNode, "lang", get_lang, 0);
|
2387
|
+
rb_define_method(cNokogiriXmlNode, "lang=", set_lang, 1);
|
2388
|
+
rb_define_method(cNokogiriXmlNode, "last_element_child", rb_xml_node_last_element_child, 0);
|
2389
|
+
rb_define_method(cNokogiriXmlNode, "line", rb_xml_node_line, 0);
|
2390
|
+
rb_define_method(cNokogiriXmlNode, "line=", rb_xml_node_line_set, 1);
|
2391
|
+
rb_define_method(cNokogiriXmlNode, "namespace", rb_xml_node_namespace, 0);
|
2392
|
+
rb_define_method(cNokogiriXmlNode, "namespace_definitions", namespace_definitions, 0);
|
2393
|
+
rb_define_method(cNokogiriXmlNode, "namespace_scopes", rb_xml_node_namespace_scopes, 0);
|
2394
|
+
rb_define_method(cNokogiriXmlNode, "namespaced_key?", namespaced_key_eh, 2);
|
2395
|
+
rb_define_method(cNokogiriXmlNode, "native_content=", set_native_content, 1);
|
2396
|
+
rb_define_method(cNokogiriXmlNode, "next_element", next_element, 0);
|
2397
|
+
rb_define_method(cNokogiriXmlNode, "next_sibling", next_sibling, 0);
|
1783
2398
|
rb_define_method(cNokogiriXmlNode, "node_name", get_name, 0);
|
1784
|
-
rb_define_method(cNokogiriXmlNode, "document", document, 0);
|
1785
2399
|
rb_define_method(cNokogiriXmlNode, "node_name=", set_name, 1);
|
2400
|
+
rb_define_method(cNokogiriXmlNode, "node_type", node_type, 0);
|
1786
2401
|
rb_define_method(cNokogiriXmlNode, "parent", get_parent, 0);
|
1787
|
-
rb_define_method(cNokogiriXmlNode, "
|
1788
|
-
rb_define_method(cNokogiriXmlNode, "
|
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);
|
2402
|
+
rb_define_method(cNokogiriXmlNode, "path", rb_xml_node_path, 0);
|
2403
|
+
rb_define_method(cNokogiriXmlNode, "pointer_id", rb_xml_node_pointer_id, 0);
|
1795
2404
|
rb_define_method(cNokogiriXmlNode, "previous_element", previous_element, 0);
|
1796
|
-
rb_define_method(cNokogiriXmlNode, "
|
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);
|
2405
|
+
rb_define_method(cNokogiriXmlNode, "previous_sibling", previous_sibling, 0);
|
1809
2406
|
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
2407
|
|
1822
|
-
rb_define_private_method(cNokogiriXmlNode, "process_xincludes", process_xincludes, 1);
|
1823
|
-
rb_define_private_method(cNokogiriXmlNode, "in_context", in_context, 2);
|
1824
2408
|
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
2409
|
rb_define_private_method(cNokogiriXmlNode, "add_next_sibling_node", add_next_sibling, 1);
|
1827
|
-
rb_define_private_method(cNokogiriXmlNode, "
|
2410
|
+
rb_define_private_method(cNokogiriXmlNode, "add_previous_sibling_node", add_previous_sibling, 1);
|
2411
|
+
rb_define_private_method(cNokogiriXmlNode, "compare", compare, 1);
|
1828
2412
|
rb_define_private_method(cNokogiriXmlNode, "dump_html", dump_html, 0);
|
1829
|
-
rb_define_private_method(cNokogiriXmlNode, "native_write_to", native_write_to, 4);
|
1830
2413
|
rb_define_private_method(cNokogiriXmlNode, "get", get, 1);
|
2414
|
+
rb_define_private_method(cNokogiriXmlNode, "in_context", in_context, 2);
|
2415
|
+
rb_define_private_method(cNokogiriXmlNode, "native_write_to", native_write_to, 4);
|
2416
|
+
rb_define_private_method(cNokogiriXmlNode, "prepend_newline?", rb_prepend_newline, 0);
|
2417
|
+
rb_define_private_method(cNokogiriXmlNode, "html_standard_serialize", html_standard_serialize, 1);
|
2418
|
+
rb_define_private_method(cNokogiriXmlNode, "process_xincludes", process_xincludes, 1);
|
2419
|
+
rb_define_private_method(cNokogiriXmlNode, "replace_node", replace, 1);
|
1831
2420
|
rb_define_private_method(cNokogiriXmlNode, "set", set, 2);
|
1832
2421
|
rb_define_private_method(cNokogiriXmlNode, "set_namespace", set_namespace, 1);
|
1833
|
-
rb_define_private_method(cNokogiriXmlNode, "compare", compare, 1);
|
1834
2422
|
|
1835
2423
|
id_decorate = rb_intern("decorate");
|
1836
2424
|
id_decorate_bang = rb_intern("decorate!");
|
1837
2425
|
}
|
1838
|
-
|
1839
|
-
/* vim: set noet sw=4 sws=4 */
|