nokogiri 1.3.2 → 1.3.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.
- data/CHANGELOG.ja.rdoc +25 -4
- data/CHANGELOG.rdoc +20 -0
- data/Manifest.txt +2 -0
- data/Rakefile +20 -21
- data/ext/nokogiri/extconf.rb +8 -1
- data/ext/nokogiri/html_document.c +0 -2
- data/ext/nokogiri/nokogiri.c +2 -0
- data/ext/nokogiri/nokogiri.h +3 -4
- data/ext/nokogiri/xml_document.c +30 -23
- data/ext/nokogiri/xml_document.h +3 -2
- data/ext/nokogiri/xml_dtd.c +4 -0
- data/ext/nokogiri/xml_dtd.h +2 -0
- data/ext/nokogiri/xml_node.c +28 -9
- data/ext/nokogiri/xml_reader.c +0 -7
- data/ext/nokogiri/xml_relax_ng.c +7 -1
- data/ext/nokogiri/xml_sax_parser.c +2 -0
- data/lib/action-nokogiri.rb +2 -0
- data/lib/nokogiri.rb +9 -3
- data/lib/nokogiri/css/generated_tokenizer.rb +80 -82
- data/lib/nokogiri/css/tokenizer.rb +1 -5
- data/lib/nokogiri/decorators/hpricot/node_set.rb +1 -1
- data/lib/nokogiri/ffi/structs/common_node.rb +1 -1
- data/lib/nokogiri/ffi/structs/xml_document.rb +1 -1
- data/lib/nokogiri/ffi/xml/document.rb +15 -4
- data/lib/nokogiri/ffi/xml/node.rb +85 -63
- data/lib/nokogiri/ffi/xml/reader.rb +4 -15
- data/lib/nokogiri/ffi/xml/relax_ng.rb +3 -1
- data/lib/nokogiri/hpricot.rb +30 -0
- data/lib/nokogiri/html/document.rb +3 -1
- data/lib/nokogiri/html/document_fragment.rb +1 -1
- data/lib/nokogiri/html/sax/parser.rb +2 -1
- data/lib/nokogiri/version.rb +1 -1
- data/lib/nokogiri/xml/builder.rb +44 -1
- data/lib/nokogiri/xml/document.rb +8 -1
- data/lib/nokogiri/xml/document_fragment.rb +1 -1
- data/lib/nokogiri/xml/fragment_handler.rb +4 -7
- data/lib/nokogiri/xml/node.rb +9 -6
- data/lib/nokogiri/xml/node_set.rb +7 -0
- data/lib/nokogiri/xml/parse_options.rb +1 -1
- data/test/css/test_nthiness.rb +2 -3
- data/test/ffi/test_document.rb +6 -6
- data/test/files/2ch.html +108 -0
- data/test/files/shift_jis.xml +5 -0
- data/test/helper.rb +3 -0
- data/test/hpricot/test_alter.rb +9 -9
- data/test/hpricot/test_builder.rb +2 -2
- data/test/hpricot/test_parser.rb +70 -146
- data/test/hpricot/test_paths.rb +2 -2
- data/test/hpricot/test_preserved.rb +2 -2
- data/test/hpricot/test_xml.rb +3 -3
- data/test/html/sax/test_parser.rb +12 -0
- data/test/html/test_builder.rb +6 -4
- data/test/html/test_document.rb +7 -0
- data/test/html/test_document_encoding.rb +17 -0
- data/test/html/test_document_fragment.rb +12 -0
- data/test/html/test_node.rb +5 -2
- data/test/test_convert_xpath.rb +1 -50
- data/test/test_css_cache.rb +1 -12
- data/test/test_nokogiri.rb +7 -0
- data/test/test_reader.rb +14 -0
- data/test/xml/test_document.rb +44 -0
- data/test/xml/test_document_fragment.rb +12 -0
- data/test/xml/test_node.rb +10 -2
- data/test/xml/test_node_encoding.rb +23 -0
- data/test/xml/test_node_set.rb +10 -0
- metadata +5 -3
data/ext/nokogiri/xml_reader.c
CHANGED
@@ -163,13 +163,6 @@ static VALUE attribute_nodes(VALUE self)
|
|
163
163
|
xmlNodePtr ptr = xmlTextReaderExpand(reader);
|
164
164
|
if(ptr == NULL) return Qnil;
|
165
165
|
|
166
|
-
// FIXME I'm not sure if this is correct..... I don't really like pointing
|
167
|
-
// at this document, but I have to because of the assertions in
|
168
|
-
// the node wrapping code.
|
169
|
-
if(! DOC_RUBY_OBJECT_TEST(ptr->doc)) {
|
170
|
-
VALUE rb_doc = Nokogiri_wrap_xml_document(cNokogiriXmlDocument, ptr->doc);
|
171
|
-
RDATA(rb_doc)->dfree = NULL;
|
172
|
-
}
|
173
166
|
VALUE enc = rb_iv_get(self, "@encoding");
|
174
167
|
|
175
168
|
if(enc != Qnil && NULL == ptr->doc->encoding) {
|
data/ext/nokogiri/xml_relax_ng.c
CHANGED
@@ -120,7 +120,9 @@ static VALUE from_document(VALUE klass, VALUE document)
|
|
120
120
|
xmlRelaxNGPtr schema = xmlRelaxNGParse(ctx);
|
121
121
|
|
122
122
|
xmlSetStructuredErrorFunc(NULL, NULL);
|
123
|
-
|
123
|
+
if (! is_2_6_16()) {
|
124
|
+
xmlRelaxNGFreeParserCtxt(ctx);
|
125
|
+
}
|
124
126
|
|
125
127
|
if(NULL == schema) {
|
126
128
|
xmlErrorPtr error = xmlGetLastError();
|
@@ -132,6 +134,10 @@ static VALUE from_document(VALUE klass, VALUE document)
|
|
132
134
|
return Qnil;
|
133
135
|
}
|
134
136
|
|
137
|
+
if (is_2_6_16()) {
|
138
|
+
xmlRelaxNGFreeParserCtxt(ctx);
|
139
|
+
}
|
140
|
+
|
135
141
|
VALUE rb_schema = Data_Wrap_Struct(klass, 0, dealloc, schema);
|
136
142
|
rb_iv_set(rb_schema, "@errors", errors);
|
137
143
|
|
@@ -310,6 +310,8 @@ static VALUE allocate(VALUE klass)
|
|
310
310
|
{
|
311
311
|
xmlSAXHandlerPtr handler = calloc(1, sizeof(xmlSAXHandler));
|
312
312
|
|
313
|
+
xmlSetStructuredErrorFunc(NULL, NULL);
|
314
|
+
|
313
315
|
handler->startDocument = start_document;
|
314
316
|
handler->endDocument = end_document;
|
315
317
|
handler->startElement = start_element;
|
data/lib/action-nokogiri.rb
CHANGED
@@ -18,6 +18,7 @@ module ActionController
|
|
18
18
|
# Get your response as a Nokogiri::XML::Document using the
|
19
19
|
# Nokogiri.HTML parser
|
20
20
|
def html(flavor=nil)
|
21
|
+
warn "@response.html is deprecated and will be removed in nokogiri 1.4.0"
|
21
22
|
if flavor == :hpricot
|
22
23
|
@_nokogiri_html_hpricot ||= Nokogiri::Hpricot(body)
|
23
24
|
else
|
@@ -29,6 +30,7 @@ module ActionController
|
|
29
30
|
# Get your response as a Nokogiri::XML::Document using the
|
30
31
|
# Nokogiri.XML parser
|
31
32
|
def xml
|
33
|
+
warn "@response.html is deprecated and will be removed in nokogiri 1.4.0"
|
32
34
|
@_nokogiri_xml ||= Nokogiri::XML(body)
|
33
35
|
end
|
34
36
|
|
data/lib/nokogiri.rb
CHANGED
@@ -54,10 +54,16 @@ module Nokogiri
|
|
54
54
|
# Parse an HTML or XML document. +string+ contains the document.
|
55
55
|
def parse string, url = nil, encoding = nil, options = nil
|
56
56
|
doc =
|
57
|
-
if string
|
58
|
-
|
57
|
+
if string.respond_to?(:read) ||
|
58
|
+
string =~ /^\s*<[^Hh>]*html/i # Probably html
|
59
|
+
Nokogiri::HTML(
|
60
|
+
string,
|
61
|
+
url,
|
62
|
+
encoding, options || XML::ParseOptions::DEFAULT_HTML
|
63
|
+
)
|
59
64
|
else
|
60
|
-
Nokogiri::XML
|
65
|
+
Nokogiri::XML(string, url, encoding,
|
66
|
+
options || XML::ParseOptions::DEFAULT_XML)
|
61
67
|
end
|
62
68
|
yield doc if block_given?
|
63
69
|
doc
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#--
|
2
2
|
# DO NOT MODIFY!!!!
|
3
|
-
# This file is automatically generated by rex 1.0.
|
3
|
+
# This file is automatically generated by rex 1.0.4
|
4
4
|
# from lexical definition file "lib/nokogiri/css/tokenizer.rex".
|
5
5
|
#++
|
6
6
|
|
@@ -11,133 +11,131 @@ class GeneratedTokenizer < GeneratedParser
|
|
11
11
|
|
12
12
|
class ScanError < StandardError ; end
|
13
13
|
|
14
|
-
attr_reader
|
15
|
-
attr_reader
|
14
|
+
attr_reader :lineno
|
15
|
+
attr_reader :filename
|
16
|
+
attr_accessor :state
|
16
17
|
|
17
|
-
def scan_setup
|
18
|
+
def scan_setup(str)
|
19
|
+
@ss = StringScanner.new(str)
|
20
|
+
@lineno = 1
|
21
|
+
@state = nil
|
22
|
+
end
|
18
23
|
|
19
|
-
def action
|
24
|
+
def action(&block)
|
20
25
|
yield
|
21
26
|
end
|
22
27
|
|
23
|
-
def scan_str(
|
24
|
-
|
28
|
+
def scan_str(str)
|
29
|
+
scan_setup(str)
|
25
30
|
do_parse
|
26
31
|
end
|
27
32
|
|
28
33
|
def load_file( filename )
|
29
34
|
@filename = filename
|
30
35
|
open(filename, "r") do |f|
|
31
|
-
|
36
|
+
scan_setup(f.read)
|
32
37
|
end
|
33
38
|
end
|
34
39
|
|
35
40
|
def scan_file( filename )
|
36
|
-
load_file
|
41
|
+
load_file(filename)
|
37
42
|
do_parse
|
38
43
|
end
|
39
44
|
|
40
|
-
def next_token
|
41
|
-
@rex_tokens.shift
|
42
|
-
end
|
43
45
|
|
44
|
-
def
|
45
|
-
|
46
|
-
@rex_tokens = []
|
47
|
-
@lineno = 1
|
48
|
-
ss = StringScanner.new(str)
|
49
|
-
state = nil
|
50
|
-
until ss.eos?
|
51
|
-
text = ss.peek(1)
|
52
|
-
@lineno += 1 if text == "\n"
|
53
|
-
case state
|
54
|
-
when nil
|
55
|
-
case
|
56
|
-
when (text = ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*\(\s*/))
|
57
|
-
@rex_tokens.push action { [:FUNCTION, text] }
|
46
|
+
def next_token
|
47
|
+
return if @ss.eos?
|
58
48
|
|
59
|
-
|
60
|
-
|
49
|
+
text = @ss.peek(1)
|
50
|
+
@lineno += 1 if text == "\n"
|
51
|
+
token = case @state
|
52
|
+
when nil
|
53
|
+
case
|
54
|
+
when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*\(\s*/))
|
55
|
+
action { [:FUNCTION, text] }
|
61
56
|
|
62
|
-
|
63
|
-
|
57
|
+
when (text = @ss.scan(/[-@]?([_A-Za-z]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*/))
|
58
|
+
action { [:IDENT, text] }
|
64
59
|
|
65
|
-
|
66
|
-
|
60
|
+
when (text = @ss.scan(/\#([_A-Za-z0-9-]|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])+/))
|
61
|
+
action { [:HASH, text] }
|
67
62
|
|
68
|
-
|
69
|
-
|
63
|
+
when (text = @ss.scan(/[\s\r\n\f]*~=[\s\r\n\f]*/))
|
64
|
+
action { [:INCLUDES, text] }
|
70
65
|
|
71
|
-
|
72
|
-
|
66
|
+
when (text = @ss.scan(/[\s\r\n\f]*\|=[\s\r\n\f]*/))
|
67
|
+
action { [:DASHMATCH, text] }
|
73
68
|
|
74
|
-
|
75
|
-
|
69
|
+
when (text = @ss.scan(/[\s\r\n\f]*\^=[\s\r\n\f]*/))
|
70
|
+
action { [:PREFIXMATCH, text] }
|
76
71
|
|
77
|
-
|
78
|
-
|
72
|
+
when (text = @ss.scan(/[\s\r\n\f]*\$=[\s\r\n\f]*/))
|
73
|
+
action { [:SUFFIXMATCH, text] }
|
79
74
|
|
80
|
-
|
81
|
-
|
75
|
+
when (text = @ss.scan(/[\s\r\n\f]*\*=[\s\r\n\f]*/))
|
76
|
+
action { [:SUBSTRINGMATCH, text] }
|
82
77
|
|
83
|
-
|
84
|
-
|
78
|
+
when (text = @ss.scan(/[\s\r\n\f]*!=[\s\r\n\f]*/))
|
79
|
+
action { [:NOT_EQUAL, text] }
|
85
80
|
|
86
|
-
|
87
|
-
|
81
|
+
when (text = @ss.scan(/[\s\r\n\f]*=[\s\r\n\f]*/))
|
82
|
+
action { [:EQUAL, text] }
|
88
83
|
|
89
|
-
|
90
|
-
|
84
|
+
when (text = @ss.scan(/[\s\r\n\f]*\)/))
|
85
|
+
action { [:RPAREN, text] }
|
91
86
|
|
92
|
-
|
93
|
-
|
87
|
+
when (text = @ss.scan(/[\s\r\n\f]*\[[\s\r\n\f]*/))
|
88
|
+
action { [:LSQUARE, text] }
|
94
89
|
|
95
|
-
|
96
|
-
|
90
|
+
when (text = @ss.scan(/[\s\r\n\f]*\]/))
|
91
|
+
action { [:RSQUARE, text] }
|
97
92
|
|
98
|
-
|
99
|
-
|
93
|
+
when (text = @ss.scan(/[\s\r\n\f]*\+[\s\r\n\f]*/))
|
94
|
+
action { [:PLUS, text] }
|
100
95
|
|
101
|
-
|
102
|
-
|
96
|
+
when (text = @ss.scan(/[\s\r\n\f]*>[\s\r\n\f]*/))
|
97
|
+
action { [:GREATER, text] }
|
103
98
|
|
104
|
-
|
105
|
-
|
99
|
+
when (text = @ss.scan(/[\s\r\n\f]*,[\s\r\n\f]*/))
|
100
|
+
action { [:COMMA, text] }
|
106
101
|
|
107
|
-
|
108
|
-
|
102
|
+
when (text = @ss.scan(/[\s\r\n\f]*~[\s\r\n\f]*/))
|
103
|
+
action { [:TILDE, text] }
|
109
104
|
|
110
|
-
|
111
|
-
|
105
|
+
when (text = @ss.scan(/\:not\([\s\r\n\f]*/))
|
106
|
+
action { [:NOT, text] }
|
112
107
|
|
113
|
-
|
114
|
-
|
108
|
+
when (text = @ss.scan(/-?([0-9]+|[0-9]*\.[0-9]+)/))
|
109
|
+
action { [:NUMBER, text] }
|
115
110
|
|
116
|
-
|
117
|
-
|
111
|
+
when (text = @ss.scan(/[\s\r\n\f]*\/\/[\s\r\n\f]*/))
|
112
|
+
action { [:DOUBLESLASH, text] }
|
118
113
|
|
119
|
-
|
120
|
-
|
114
|
+
when (text = @ss.scan(/[\s\r\n\f]*\/[\s\r\n\f]*/))
|
115
|
+
action { [:SLASH, text] }
|
121
116
|
|
122
|
-
|
123
|
-
|
117
|
+
when (text = @ss.scan(/U\+[0-9a-f?]{1,6}(-[0-9a-f]{1,6})?/))
|
118
|
+
action {[:UNICODE_RANGE, text] }
|
124
119
|
|
125
|
-
|
126
|
-
|
120
|
+
when (text = @ss.scan(/[\s\t\r\n\f]+/))
|
121
|
+
action { [:S, text] }
|
127
122
|
|
128
|
-
|
129
|
-
|
123
|
+
when (text = @ss.scan(/"([^\n\r\f"]|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*"|'([^\n\r\f']|\n|\r\n|\r|\f|[^\0-\177]|\\[0-9A-Fa-f]{1,6}(\r\n|[\s\n\r\t\f])?|\\[^\n\r\f0-9A-Fa-f])*'/))
|
124
|
+
action { [:STRING, text] }
|
130
125
|
|
131
|
-
|
132
|
-
|
133
|
-
raise ScanError, "can not match: '" + text + "'"
|
134
|
-
end # if
|
126
|
+
when (text = @ss.scan(/./))
|
127
|
+
action { [text, text] }
|
135
128
|
|
136
129
|
else
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
130
|
+
text = @ss.string[@ss.pos .. -1]
|
131
|
+
raise ScanError, "can not match: '" + text + "'"
|
132
|
+
end # if
|
133
|
+
|
134
|
+
else
|
135
|
+
raise ScanError, "undefined state: '" + state.to_s + "'"
|
136
|
+
end # case state
|
137
|
+
token
|
138
|
+
end # def next_token
|
141
139
|
|
142
140
|
end # class
|
143
141
|
end
|
@@ -18,7 +18,7 @@ module Nokogiri
|
|
18
18
|
def keep_reference_from_document! # equivalent to NOKOGIRI_ROOT_NODE
|
19
19
|
doc = self.document
|
20
20
|
raise "no document to add reference to" unless doc
|
21
|
-
LibXML.xmlXPathNodeSetAdd(doc.
|
21
|
+
LibXML.xmlXPathNodeSetAdd(doc.unlinked_nodes, self)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -8,9 +8,19 @@ module Nokogiri
|
|
8
8
|
cstruct[:URL]
|
9
9
|
end
|
10
10
|
|
11
|
-
def root=(
|
12
|
-
|
13
|
-
|
11
|
+
def root=(new_root) # :nodoc:
|
12
|
+
old_root = nil
|
13
|
+
if new_root.cstruct[:doc] != cstruct[:doc]
|
14
|
+
old_root_ptr = LibXML.xmlDocGetRootElement(cstruct)
|
15
|
+
new_root_ptr = LibXML.xmlDocCopyNode(new_root.cstruct, cstruct, 1)
|
16
|
+
raise RuntimeError "Could not reparent node (xmlDocCopyNode)" if new_root_ptr.null?
|
17
|
+
new_root = Node.wrap(new_root_ptr)
|
18
|
+
end
|
19
|
+
LibXML.xmlDocSetRootElement(cstruct, new_root.cstruct)
|
20
|
+
if old_root_ptr && ! old_root_ptr.null?
|
21
|
+
LibXML::XmlNode.new(old_root_ptr).keep_reference_from_document!
|
22
|
+
end
|
23
|
+
new_root
|
14
24
|
end
|
15
25
|
|
16
26
|
def root # :nodoc:
|
@@ -24,7 +34,8 @@ module Nokogiri
|
|
24
34
|
end
|
25
35
|
|
26
36
|
def encoding # :nodoc:
|
27
|
-
cstruct[:encoding]
|
37
|
+
ptr = cstruct[:encoding]
|
38
|
+
ptr.null? ? nil : ptr.read_string
|
28
39
|
end
|
29
40
|
|
30
41
|
def self.read_io(io, url, encoding, options) # :nodoc:
|
@@ -1,14 +1,15 @@
|
|
1
1
|
module Nokogiri
|
2
2
|
module XML
|
3
3
|
class Node
|
4
|
+
# :stopdoc:
|
4
5
|
|
5
|
-
attr_accessor :cstruct
|
6
|
+
attr_accessor :cstruct
|
6
7
|
|
7
|
-
def pointer_id
|
8
|
+
def pointer_id
|
8
9
|
cstruct.pointer
|
9
10
|
end
|
10
11
|
|
11
|
-
def encode_special_chars(string)
|
12
|
+
def encode_special_chars(string)
|
12
13
|
char_ptr = LibXML.xmlEncodeSpecialChars(self[:doc], string)
|
13
14
|
encoded = char_ptr.read_string
|
14
15
|
# TODO: encoding?
|
@@ -16,7 +17,7 @@ module Nokogiri
|
|
16
17
|
encoded
|
17
18
|
end
|
18
19
|
|
19
|
-
def internal_subset
|
20
|
+
def internal_subset
|
20
21
|
return nil if cstruct[:doc].null?
|
21
22
|
doc = cstruct.document
|
22
23
|
dtd = LibXML.xmlGetIntSubset(doc)
|
@@ -24,37 +25,37 @@ module Nokogiri
|
|
24
25
|
Node.wrap(dtd)
|
25
26
|
end
|
26
27
|
|
27
|
-
def dup(deep = 1)
|
28
|
+
def dup(deep = 1)
|
28
29
|
dup_ptr = LibXML.xmlDocCopyNode(cstruct, cstruct.document, deep)
|
29
30
|
return nil if dup_ptr.null?
|
30
31
|
Node.wrap(dup_ptr, self.class)
|
31
32
|
end
|
32
33
|
|
33
|
-
def unlink
|
34
|
+
def unlink
|
34
35
|
LibXML.xmlUnlinkNode(cstruct)
|
35
36
|
cstruct.keep_reference_from_document!
|
36
37
|
self
|
37
38
|
end
|
38
39
|
|
39
|
-
def blank?
|
40
|
+
def blank?
|
40
41
|
LibXML.xmlIsBlankNode(cstruct) == 1
|
41
42
|
end
|
42
43
|
|
43
|
-
def next_sibling
|
44
|
+
def next_sibling
|
44
45
|
cstruct_node_from :next
|
45
46
|
end
|
46
47
|
|
47
|
-
def previous_sibling
|
48
|
+
def previous_sibling
|
48
49
|
cstruct_node_from :prev
|
49
50
|
end
|
50
51
|
|
51
|
-
def replace_with_node(new_node)
|
52
|
+
def replace_with_node(new_node)
|
52
53
|
LibXML.xmlReplaceNode(cstruct, new_node.cstruct)
|
53
54
|
Node.send(:relink_namespace, new_node.cstruct)
|
54
55
|
self
|
55
56
|
end
|
56
57
|
|
57
|
-
def children
|
58
|
+
def children
|
58
59
|
return NodeSet.new(nil) if cstruct[:children].null?
|
59
60
|
child = Node.wrap(cstruct[:children])
|
60
61
|
|
@@ -74,26 +75,26 @@ module Nokogiri
|
|
74
75
|
return set
|
75
76
|
end
|
76
77
|
|
77
|
-
def child
|
78
|
+
def child
|
78
79
|
(val = cstruct[:children]).null? ? nil : Node.wrap(val)
|
79
80
|
end
|
80
81
|
|
81
|
-
def key?(attribute)
|
82
|
+
def key?(attribute)
|
82
83
|
! (prop = LibXML.xmlHasProp(cstruct, attribute.to_s)).null?
|
83
84
|
end
|
84
85
|
|
85
|
-
def namespaced_key?(attribute, namespace)
|
86
|
+
def namespaced_key?(attribute, namespace)
|
86
87
|
prop = LibXML.xmlHasNsProp(cstruct, attribute.to_s,
|
87
88
|
namespace.nil? ? nil : namespace.to_s)
|
88
89
|
prop.null? ? false : true
|
89
90
|
end
|
90
91
|
|
91
|
-
def []=(property, value)
|
92
|
+
def []=(property, value)
|
92
93
|
LibXML.xmlSetProp(cstruct, property, value)
|
93
94
|
value
|
94
95
|
end
|
95
96
|
|
96
|
-
def get(attribute)
|
97
|
+
def get(attribute)
|
97
98
|
return nil unless attribute
|
98
99
|
propstr = LibXML.xmlGetProp(cstruct, attribute.to_s)
|
99
100
|
return nil if propstr.null?
|
@@ -107,33 +108,26 @@ module Nokogiri
|
|
107
108
|
self
|
108
109
|
end
|
109
110
|
|
110
|
-
def attribute(name)
|
111
|
+
def attribute(name)
|
111
112
|
raise "Node#attribute not implemented yet"
|
112
113
|
end
|
113
114
|
|
114
|
-
def attribute_with_ns(name, namespace)
|
115
|
+
def attribute_with_ns(name, namespace)
|
115
116
|
prop = LibXML.xmlHasNsProp(cstruct, name.to_s,
|
116
117
|
namespace.nil? ? NULL : namespace.to_s)
|
117
118
|
return prop if prop.null?
|
118
119
|
Node.wrap(prop)
|
119
120
|
end
|
120
121
|
|
121
|
-
def attribute_nodes
|
122
|
-
|
123
|
-
prop_cstruct = cstruct[:properties]
|
124
|
-
while ! prop_cstruct.null?
|
125
|
-
prop = Node.wrap(prop_cstruct)
|
126
|
-
attr << prop
|
127
|
-
prop_cstruct = prop.cstruct[:next]
|
128
|
-
end
|
129
|
-
attr
|
122
|
+
def attribute_nodes
|
123
|
+
Node.node_properties cstruct
|
130
124
|
end
|
131
125
|
|
132
|
-
def namespace
|
126
|
+
def namespace
|
133
127
|
cstruct[:ns].null? ? nil : Namespace.wrap(cstruct.document, cstruct[:ns])
|
134
128
|
end
|
135
129
|
|
136
|
-
def namespace_definitions
|
130
|
+
def namespace_definitions
|
137
131
|
list = []
|
138
132
|
ns_ptr = cstruct[:nsDef]
|
139
133
|
return list if ns_ptr.null?
|
@@ -145,16 +139,16 @@ module Nokogiri
|
|
145
139
|
list
|
146
140
|
end
|
147
141
|
|
148
|
-
def node_type
|
142
|
+
def node_type
|
149
143
|
cstruct[:type]
|
150
144
|
end
|
151
145
|
|
152
|
-
def native_content=(content)
|
146
|
+
def native_content=(content)
|
153
147
|
LibXML.xmlNodeSetContent(cstruct, content)
|
154
148
|
content
|
155
149
|
end
|
156
150
|
|
157
|
-
def content
|
151
|
+
def content
|
158
152
|
content_ptr = LibXML.xmlNodeGetContent(cstruct)
|
159
153
|
return nil if content_ptr.null?
|
160
154
|
content = content_ptr.read_string # TODO: encoding?
|
@@ -162,45 +156,45 @@ module Nokogiri
|
|
162
156
|
content
|
163
157
|
end
|
164
158
|
|
165
|
-
def add_child(child)
|
159
|
+
def add_child(child)
|
166
160
|
Node.reparent_node_with(child, self) do |child_cstruct, my_cstruct|
|
167
161
|
LibXML.xmlAddChild(my_cstruct, child_cstruct)
|
168
162
|
end
|
169
163
|
end
|
170
164
|
|
171
|
-
def parent
|
165
|
+
def parent
|
172
166
|
cstruct_node_from :parent
|
173
167
|
end
|
174
|
-
|
175
|
-
def node_name=(string)
|
168
|
+
|
169
|
+
def node_name=(string)
|
176
170
|
LibXML.xmlNodeSetName(cstruct, string)
|
177
171
|
string
|
178
172
|
end
|
179
173
|
|
180
|
-
def node_name
|
174
|
+
def node_name
|
181
175
|
cstruct[:name] # TODO: encoding?
|
182
176
|
end
|
183
177
|
|
184
|
-
def path
|
178
|
+
def path
|
185
179
|
path_ptr = LibXML.xmlGetNodePath(cstruct)
|
186
180
|
val = path_ptr.null? ? nil : path_ptr.read_string # TODO: encoding?
|
187
181
|
LibXML.xmlFree(path_ptr)
|
188
182
|
val
|
189
183
|
end
|
190
184
|
|
191
|
-
def add_next_sibling(next_sibling)
|
185
|
+
def add_next_sibling(next_sibling)
|
192
186
|
Node.reparent_node_with(next_sibling, self) do |sibling_cstruct, my_cstruct|
|
193
187
|
LibXML.xmlAddNextSibling(my_cstruct, sibling_cstruct)
|
194
188
|
end
|
195
189
|
end
|
196
190
|
|
197
|
-
def add_previous_sibling(prev_sibling)
|
191
|
+
def add_previous_sibling(prev_sibling)
|
198
192
|
Node.reparent_node_with(prev_sibling, self) do |sibling_cstruct, my_cstruct|
|
199
193
|
LibXML.xmlAddPrevSibling(my_cstruct, sibling_cstruct)
|
200
194
|
end
|
201
195
|
end
|
202
196
|
|
203
|
-
def native_write_to(io, encoding, indent_string, options)
|
197
|
+
def native_write_to(io, encoding, indent_string, options)
|
204
198
|
set_xml_indent_tree_output 1
|
205
199
|
set_xml_tree_indent_string indent_string
|
206
200
|
savectx = LibXML.xmlSaveToIO(IoCallbacks.writer(io), nil, nil, encoding, options)
|
@@ -209,11 +203,11 @@ module Nokogiri
|
|
209
203
|
io
|
210
204
|
end
|
211
205
|
|
212
|
-
def line
|
206
|
+
def line
|
213
207
|
cstruct[:line]
|
214
208
|
end
|
215
209
|
|
216
|
-
def add_namespace_definition(prefix, href)
|
210
|
+
def add_namespace_definition(prefix, href)
|
217
211
|
ns = LibXML.xmlNewNs(cstruct, href, prefix)
|
218
212
|
if ns.null?
|
219
213
|
ns = LibXML.xmlSearchNs(cstruct.document, cstruct,
|
@@ -223,43 +217,46 @@ module Nokogiri
|
|
223
217
|
Namespace.wrap(cstruct.document, ns)
|
224
218
|
end
|
225
219
|
|
226
|
-
def self.new(name,
|
220
|
+
def self.new(name, doc, *rest)
|
227
221
|
ptr = LibXML.xmlNewNode(nil, name.to_s)
|
228
222
|
|
229
223
|
node_cstruct = LibXML::XmlNode.new(ptr)
|
230
|
-
node_cstruct[:doc] =
|
224
|
+
node_cstruct[:doc] = doc.cstruct[:doc]
|
231
225
|
node_cstruct.keep_reference_from_document!
|
232
226
|
|
233
|
-
node = Node.wrap(
|
234
|
-
|
227
|
+
node = Node.wrap(
|
228
|
+
node_cstruct,
|
229
|
+
Node == self ? nil : self
|
230
|
+
)
|
231
|
+
node.send :initialize, name, doc, *rest
|
235
232
|
yield node if block_given?
|
236
233
|
node
|
237
234
|
end
|
238
235
|
|
239
|
-
def dump_html
|
236
|
+
def dump_html
|
240
237
|
return to_xml if type == DOCUMENT_NODE
|
241
238
|
buffer = LibXML::XmlBuffer.new(LibXML.xmlBufferCreate())
|
242
239
|
LibXML.htmlNodeDump(buffer, cstruct[:doc], cstruct)
|
243
240
|
buffer[:content] # TODO: encoding?
|
244
241
|
end
|
245
242
|
|
246
|
-
def compare(other)
|
243
|
+
def compare(other)
|
247
244
|
LibXML.xmlXPathCmpNodes(other.cstruct, self.cstruct)
|
248
245
|
end
|
249
246
|
|
250
|
-
def self.wrap(node_struct, klass=nil)
|
247
|
+
def self.wrap(node_struct, klass=nil)
|
251
248
|
if node_struct.is_a?(FFI::Pointer)
|
252
249
|
# cast native pointers up into a node cstruct
|
253
250
|
return nil if node_struct.null?
|
254
|
-
node_struct = LibXML::XmlNode.new(node_struct)
|
251
|
+
node_struct = LibXML::XmlNode.new(node_struct)
|
255
252
|
end
|
256
253
|
|
257
254
|
raise "wrapping a node without a document" unless node_struct.document
|
258
255
|
|
259
256
|
document_struct = node_struct.document
|
260
|
-
|
257
|
+
document_obj = document_struct.nil? ? nil : document_struct.ruby_doc
|
261
258
|
if node_struct[:type] == DOCUMENT_NODE || node_struct[:type] == HTML_DOCUMENT_NODE
|
262
|
-
return
|
259
|
+
return document_obj
|
263
260
|
end
|
264
261
|
|
265
262
|
ruby_node = node_struct.ruby_node
|
@@ -288,11 +285,13 @@ module Nokogiri
|
|
288
285
|
|
289
286
|
node.cstruct.ruby_node = node
|
290
287
|
|
291
|
-
|
292
|
-
|
288
|
+
if document_obj
|
289
|
+
node.instance_variable_set(:@document, document_obj)
|
290
|
+
cache = document_obj.instance_variable_get(:@node_cache)
|
291
|
+
cache << node
|
292
|
+
document_obj.decorate(node)
|
293
|
+
end
|
293
294
|
|
294
|
-
node.instance_variable_set(:@document, document)
|
295
|
-
document.decorate(node)
|
296
295
|
node
|
297
296
|
end
|
298
297
|
|
@@ -300,11 +299,33 @@ module Nokogiri
|
|
300
299
|
cstruct.document.ruby_doc
|
301
300
|
end
|
302
301
|
|
302
|
+
class << self
|
303
|
+
def node_properties(cstruct)
|
304
|
+
attr = []
|
305
|
+
prop_cstruct = cstruct[:properties]
|
306
|
+
while ! prop_cstruct.null?
|
307
|
+
prop = Node.wrap(prop_cstruct)
|
308
|
+
attr << prop
|
309
|
+
prop_cstruct = prop.cstruct[:next]
|
310
|
+
end
|
311
|
+
attr
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
303
315
|
private
|
304
316
|
|
305
|
-
def self.reparent_node_with(node, other, &block)
|
317
|
+
def self.reparent_node_with(node, other, &block)
|
306
318
|
raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(Nokogiri::XML::Node)
|
307
319
|
|
320
|
+
# If a document fragment is added, we need to reparent all of it's
|
321
|
+
# children
|
322
|
+
if node.type == DOCUMENT_FRAG_NODE
|
323
|
+
node.children.each do |child|
|
324
|
+
reparent_node_with(child, other, &block)
|
325
|
+
end
|
326
|
+
return node
|
327
|
+
end
|
328
|
+
|
308
329
|
if node.cstruct[:doc] == other.cstruct[:doc]
|
309
330
|
LibXML.xmlUnlinkNode(node.cstruct)
|
310
331
|
if node.type == TEXT_NODE && other.type == TEXT_NODE && Nokogiri.is_2_6_16?
|
@@ -320,7 +341,7 @@ module Nokogiri
|
|
320
341
|
LibXML.xmlUnlinkNode(node.cstruct)
|
321
342
|
node.cstruct.keep_reference_from_document!
|
322
343
|
end
|
323
|
-
|
344
|
+
|
324
345
|
reparented_struct = LibXML::XmlNode.new(reparented_struct)
|
325
346
|
|
326
347
|
# the child was a text node that was coalesced. we need to have the object
|
@@ -336,7 +357,7 @@ module Nokogiri
|
|
336
357
|
reparented
|
337
358
|
end
|
338
359
|
|
339
|
-
def self.relink_namespace(reparented_struct)
|
360
|
+
def self.relink_namespace(reparented_struct)
|
340
361
|
# Make sure that our reparented node has the correct namespaces
|
341
362
|
if reparented_struct[:doc] != reparented_struct[:parent]
|
342
363
|
LibXML.xmlSetNs(reparented_struct, LibXML::XmlNode.new(reparented_struct[:parent])[:ns])
|
@@ -365,18 +386,19 @@ module Nokogiri
|
|
365
386
|
end
|
366
387
|
end
|
367
388
|
|
368
|
-
def cstruct_node_from(sym)
|
389
|
+
def cstruct_node_from(sym)
|
369
390
|
(val = cstruct[sym]).null? ? nil : Node.wrap(val)
|
370
391
|
end
|
371
392
|
|
372
|
-
def set_xml_indent_tree_output(value)
|
393
|
+
def set_xml_indent_tree_output(value)
|
373
394
|
LibXML.__xmlIndentTreeOutput.write_int(value)
|
374
395
|
end
|
375
396
|
|
376
|
-
def set_xml_tree_indent_string(value)
|
397
|
+
def set_xml_tree_indent_string(value)
|
377
398
|
LibXML.__xmlTreeIndentString.write_pointer(LibXML.xmlStrdup(value.to_s))
|
378
399
|
end
|
379
400
|
|
401
|
+
# :startdoc:
|
380
402
|
end
|
381
403
|
end
|
382
404
|
end
|