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