nokogiri 1.2.3 → 1.3.0
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/.autotest +14 -2
- data/CHANGELOG.ja.rdoc +38 -0
- data/CHANGELOG.rdoc +43 -0
- data/Manifest.txt +80 -5
- data/README.ja.rdoc +12 -11
- data/README.rdoc +4 -2
- data/Rakefile +103 -173
- data/bin/nokogiri +47 -0
- data/ext/nokogiri/extconf.rb +19 -13
- data/ext/nokogiri/html_document.c +39 -3
- data/ext/nokogiri/html_document.h +1 -1
- data/ext/nokogiri/html_element_description.c +272 -0
- data/ext/nokogiri/html_element_description.h +10 -0
- data/ext/nokogiri/html_entity_lookup.h +1 -1
- data/ext/nokogiri/html_sax_parser.h +1 -1
- data/ext/nokogiri/{native.c → nokogiri.c} +11 -3
- data/ext/nokogiri/{native.h → nokogiri.h} +18 -4
- data/ext/nokogiri/xml_attr.c +14 -5
- data/ext/nokogiri/xml_attr.h +1 -1
- data/ext/nokogiri/xml_cdata.c +15 -6
- data/ext/nokogiri/xml_cdata.h +1 -1
- data/ext/nokogiri/xml_comment.c +13 -4
- data/ext/nokogiri/xml_comment.h +1 -1
- data/ext/nokogiri/xml_document.c +50 -41
- data/ext/nokogiri/xml_document.h +1 -1
- data/ext/nokogiri/xml_document_fragment.c +12 -4
- data/ext/nokogiri/xml_document_fragment.h +1 -1
- data/ext/nokogiri/xml_dtd.c +1 -1
- data/ext/nokogiri/xml_dtd.h +1 -1
- data/ext/nokogiri/xml_entity_reference.c +13 -4
- data/ext/nokogiri/xml_entity_reference.h +1 -1
- data/ext/nokogiri/xml_io.h +1 -1
- data/ext/nokogiri/xml_namespace.c +69 -0
- data/ext/nokogiri/xml_namespace.h +12 -0
- data/ext/nokogiri/xml_node.c +232 -124
- data/ext/nokogiri/xml_node.h +3 -4
- data/ext/nokogiri/xml_node_set.c +206 -19
- data/ext/nokogiri/xml_node_set.h +1 -1
- data/ext/nokogiri/xml_processing_instruction.c +14 -4
- data/ext/nokogiri/xml_processing_instruction.h +1 -1
- data/ext/nokogiri/xml_reader.c +87 -7
- data/ext/nokogiri/xml_reader.h +1 -1
- data/ext/nokogiri/xml_relax_ng.c +106 -0
- data/ext/nokogiri/xml_relax_ng.h +9 -0
- data/ext/nokogiri/xml_sax_parser.c +122 -2
- data/ext/nokogiri/xml_sax_parser.h +1 -1
- data/ext/nokogiri/xml_sax_push_parser.c +1 -0
- data/ext/nokogiri/xml_sax_push_parser.h +1 -1
- data/ext/nokogiri/xml_schema.c +107 -0
- data/ext/nokogiri/xml_schema.h +9 -0
- data/ext/nokogiri/xml_syntax_error.h +1 -1
- data/ext/nokogiri/xml_text.c +10 -3
- data/ext/nokogiri/xml_text.h +1 -1
- data/ext/nokogiri/xml_xpath.h +1 -1
- data/ext/nokogiri/xml_xpath_context.h +1 -1
- data/ext/nokogiri/xslt_stylesheet.c +29 -16
- data/ext/nokogiri/xslt_stylesheet.h +1 -1
- data/lib/action-nokogiri.rb +7 -1
- data/lib/nokogiri.rb +21 -5
- data/lib/nokogiri/css/generated_parser.rb +49 -14
- data/lib/nokogiri/css/generated_tokenizer.rb +2 -2
- data/lib/nokogiri/css/node.rb +13 -3
- data/lib/nokogiri/css/parser.rb +8 -0
- data/lib/nokogiri/css/parser.y +7 -7
- data/lib/nokogiri/css/tokenizer.rb +2 -0
- data/lib/nokogiri/css/xpath_visitor.rb +10 -6
- data/lib/nokogiri/decorators/hpricot/node.rb +1 -1
- data/lib/nokogiri/decorators/hpricot/node_set.rb +2 -2
- data/lib/nokogiri/decorators/hpricot/xpath_visitor.rb +2 -0
- data/lib/nokogiri/decorators/slop.rb +3 -1
- data/lib/nokogiri/ffi/html/document.rb +37 -0
- data/lib/nokogiri/ffi/html/element_description.rb +85 -0
- data/lib/nokogiri/ffi/html/entity_lookup.rb +16 -0
- data/lib/nokogiri/ffi/html/sax/parser.rb +21 -0
- data/lib/nokogiri/ffi/io_callbacks.rb +32 -0
- data/lib/nokogiri/ffi/libxml.rb +314 -0
- data/lib/nokogiri/ffi/structs/common_node.rb +26 -0
- data/lib/nokogiri/ffi/structs/html_elem_desc.rb +24 -0
- data/lib/nokogiri/ffi/structs/html_entity_desc.rb +13 -0
- data/lib/nokogiri/ffi/structs/xml_alloc.rb +16 -0
- data/lib/nokogiri/ffi/structs/xml_attr.rb +19 -0
- data/lib/nokogiri/ffi/structs/xml_buffer.rb +16 -0
- data/lib/nokogiri/ffi/structs/xml_document.rb +108 -0
- data/lib/nokogiri/ffi/structs/xml_dtd.rb +26 -0
- data/lib/nokogiri/ffi/structs/xml_node.rb +28 -0
- data/lib/nokogiri/ffi/structs/xml_node_set.rb +53 -0
- data/lib/nokogiri/ffi/structs/xml_notation.rb +11 -0
- data/lib/nokogiri/ffi/structs/xml_ns.rb +15 -0
- data/lib/nokogiri/ffi/structs/xml_relax_ng.rb +14 -0
- data/lib/nokogiri/ffi/structs/xml_sax_handler.rb +51 -0
- data/lib/nokogiri/ffi/structs/xml_sax_push_parser_context.rb +14 -0
- data/lib/nokogiri/ffi/structs/xml_schema.rb +13 -0
- data/lib/nokogiri/ffi/structs/xml_syntax_error.rb +31 -0
- data/lib/nokogiri/ffi/structs/xml_text_reader.rb +12 -0
- data/lib/nokogiri/ffi/structs/xml_xpath_context.rb +37 -0
- data/lib/nokogiri/ffi/structs/xml_xpath_object.rb +35 -0
- data/lib/nokogiri/ffi/structs/xml_xpath_parser_context.rb +20 -0
- data/lib/nokogiri/ffi/structs/xslt_stylesheet.rb +13 -0
- data/lib/nokogiri/ffi/xml/attr.rb +41 -0
- data/lib/nokogiri/ffi/xml/cdata.rb +19 -0
- data/lib/nokogiri/ffi/xml/comment.rb +18 -0
- data/lib/nokogiri/ffi/xml/document.rb +107 -0
- data/lib/nokogiri/ffi/xml/document_fragment.rb +26 -0
- data/lib/nokogiri/ffi/xml/dtd.rb +42 -0
- data/lib/nokogiri/ffi/xml/entity_reference.rb +19 -0
- data/lib/nokogiri/ffi/xml/namespace.rb +38 -0
- data/lib/nokogiri/ffi/xml/node.rb +380 -0
- data/lib/nokogiri/ffi/xml/node_set.rb +130 -0
- data/lib/nokogiri/ffi/xml/processing_instruction.rb +20 -0
- data/lib/nokogiri/ffi/xml/reader.rb +217 -0
- data/lib/nokogiri/ffi/xml/relax_ng.rb +51 -0
- data/lib/nokogiri/ffi/xml/sax/parser.rb +148 -0
- data/lib/nokogiri/ffi/xml/sax/push_parser.rb +38 -0
- data/lib/nokogiri/ffi/xml/schema.rb +55 -0
- data/lib/nokogiri/ffi/xml/syntax_error.rb +76 -0
- data/lib/nokogiri/ffi/xml/text.rb +18 -0
- data/lib/nokogiri/ffi/xml/xpath.rb +19 -0
- data/lib/nokogiri/ffi/xml/xpath_context.rb +135 -0
- data/lib/nokogiri/ffi/xslt/stylesheet.rb +47 -0
- data/lib/nokogiri/hpricot.rb +14 -3
- data/lib/nokogiri/html.rb +11 -46
- data/lib/nokogiri/html/builder.rb +27 -1
- data/lib/nokogiri/html/document.rb +62 -6
- data/lib/nokogiri/html/document_fragment.rb +15 -0
- data/lib/nokogiri/html/element_description.rb +23 -0
- data/lib/nokogiri/html/entity_lookup.rb +2 -0
- data/lib/nokogiri/html/sax/parser.rb +27 -1
- data/lib/nokogiri/version.rb +26 -1
- data/lib/nokogiri/version_warning.rb +11 -0
- data/lib/nokogiri/xml.rb +25 -51
- data/lib/nokogiri/xml/builder.rb +166 -10
- data/lib/nokogiri/xml/cdata.rb +3 -1
- data/lib/nokogiri/xml/document.rb +39 -6
- data/lib/nokogiri/xml/document_fragment.rb +41 -1
- data/lib/nokogiri/xml/dtd.rb +3 -1
- data/lib/nokogiri/xml/entity_declaration.rb +3 -1
- data/lib/nokogiri/xml/fragment_handler.rb +24 -3
- data/lib/nokogiri/xml/namespace.rb +7 -0
- data/lib/nokogiri/xml/node.rb +314 -65
- data/lib/nokogiri/xml/node/save_options.rb +12 -2
- data/lib/nokogiri/xml/node_set.rb +58 -8
- data/lib/nokogiri/xml/parse_options.rb +80 -0
- data/lib/nokogiri/xml/processing_instruction.rb +2 -0
- data/lib/nokogiri/xml/reader.rb +42 -3
- data/lib/nokogiri/xml/relax_ng.rb +32 -0
- data/lib/nokogiri/xml/sax.rb +0 -7
- data/lib/nokogiri/xml/sax/document.rb +84 -0
- data/lib/nokogiri/xml/sax/parser.rb +38 -2
- data/lib/nokogiri/xml/sax/push_parser.rb +12 -0
- data/lib/nokogiri/xml/schema.rb +65 -0
- data/lib/nokogiri/xml/syntax_error.rb +11 -0
- data/lib/nokogiri/xml/xpath.rb +1 -1
- data/lib/nokogiri/xml/xpath_context.rb +2 -0
- data/lib/nokogiri/xslt.rb +21 -1
- data/lib/nokogiri/xslt/stylesheet.rb +19 -0
- data/lib/xsd/xmlparser/nokogiri.rb +12 -2
- data/tasks/test.rb +42 -19
- data/test/css/test_parser.rb +29 -0
- data/test/ffi/test_document.rb +35 -0
- data/test/files/address_book.rlx +12 -0
- data/test/files/address_book.xml +10 -0
- data/test/files/po.xml +32 -0
- data/test/files/po.xsd +66 -0
- data/test/helper.rb +38 -8
- data/test/html/sax/test_parser.rb +12 -0
- data/test/html/test_builder.rb +25 -2
- data/test/html/test_document.rb +91 -20
- data/test/html/test_document_fragment.rb +97 -0
- data/test/html/test_element_description.rb +95 -0
- data/test/html/test_node.rb +66 -3
- data/test/test_convert_xpath.rb +1 -1
- data/test/test_memory_leak.rb +57 -18
- data/test/test_nokogiri.rb +24 -2
- data/test/test_reader.rb +77 -0
- data/test/test_xslt_transforms.rb +120 -82
- data/test/xml/node/test_subclass.rb +44 -0
- data/test/xml/sax/test_parser.rb +9 -0
- data/test/xml/sax/test_push_parser.rb +24 -0
- data/test/xml/test_attr.rb +7 -0
- data/test/xml/test_builder.rb +48 -0
- data/test/xml/test_cdata.rb +19 -0
- data/test/xml/test_comment.rb +6 -0
- data/test/xml/test_document.rb +101 -2
- data/test/xml/test_document_fragment.rb +55 -3
- data/test/xml/test_entity_reference.rb +4 -0
- data/test/xml/test_namespace.rb +43 -0
- data/test/xml/test_node.rb +255 -8
- data/test/xml/test_node_attributes.rb +34 -0
- data/test/xml/test_node_encoding.rb +9 -2
- data/test/xml/test_node_set.rb +197 -1
- data/test/xml/test_parse_options.rb +52 -0
- data/test/xml/test_processing_instruction.rb +5 -0
- data/test/xml/test_relax_ng.rb +60 -0
- data/test/xml/test_schema.rb +65 -0
- data/test/xml/test_text.rb +5 -0
- data/test/xml/test_unparented_node.rb +3 -3
- metadata +128 -12
- data/lib/nokogiri/xml/comment.rb +0 -6
- data/lib/nokogiri/xml/element.rb +0 -6
- data/lib/nokogiri/xml/text.rb +0 -6
@@ -0,0 +1,38 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module XML
|
3
|
+
class Namespace # :nodoc:
|
4
|
+
|
5
|
+
attr_accessor :cstruct # :nodoc:
|
6
|
+
attr_accessor :document # :nodoc:
|
7
|
+
|
8
|
+
def prefix # :nodoc:
|
9
|
+
cstruct[:prefix].nil? ? nil : cstruct[:prefix] # TODO: encoding?
|
10
|
+
end
|
11
|
+
|
12
|
+
def href # :nodoc:
|
13
|
+
cstruct[:href].nil? ? nil : cstruct[:href] # TODO: encoding?
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def wrap(document, node_struct) # :nodoc:
|
18
|
+
if node_struct.is_a?(FFI::Pointer)
|
19
|
+
# cast native pointers up into a node cstruct
|
20
|
+
return nil if node_struct.null?
|
21
|
+
node_struct = LibXML::XmlNs.new(node_struct)
|
22
|
+
end
|
23
|
+
|
24
|
+
ruby_node = node_struct.ruby_node
|
25
|
+
return ruby_node unless ruby_node.nil?
|
26
|
+
|
27
|
+
ns = Nokogiri::XML::Namespace.allocate
|
28
|
+
ns.document = document.ruby_doc
|
29
|
+
ns.cstruct = node_struct
|
30
|
+
|
31
|
+
ns.cstruct.ruby_node = ns
|
32
|
+
ns
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,380 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module XML
|
3
|
+
class Node
|
4
|
+
|
5
|
+
attr_accessor :cstruct # :nodoc:
|
6
|
+
|
7
|
+
def pointer_id # :nodoc:
|
8
|
+
cstruct.pointer
|
9
|
+
end
|
10
|
+
|
11
|
+
def encode_special_chars(string) # :nodoc:
|
12
|
+
char_ptr = LibXML.xmlEncodeSpecialChars(self[:doc], string)
|
13
|
+
encoded = char_ptr.read_string
|
14
|
+
# TODO: encoding?
|
15
|
+
LibXML.xmlFree(char_ptr)
|
16
|
+
encoded
|
17
|
+
end
|
18
|
+
|
19
|
+
def internal_subset # :nodoc:
|
20
|
+
return nil if cstruct[:doc].null?
|
21
|
+
doc = cstruct.document
|
22
|
+
dtd = LibXML.xmlGetIntSubset(doc)
|
23
|
+
return nil if dtd.null?
|
24
|
+
Node.wrap(dtd)
|
25
|
+
end
|
26
|
+
|
27
|
+
def dup(deep = 1) # :nodoc:
|
28
|
+
dup_ptr = LibXML.xmlDocCopyNode(cstruct, cstruct.document, deep)
|
29
|
+
return nil if dup_ptr.null?
|
30
|
+
Node.wrap(dup_ptr, self.class)
|
31
|
+
end
|
32
|
+
|
33
|
+
def unlink # :nodoc:
|
34
|
+
LibXML.xmlUnlinkNode(cstruct)
|
35
|
+
cstruct.keep_reference_from_document!
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def blank? # :nodoc:
|
40
|
+
LibXML.xmlIsBlankNode(cstruct) == 1
|
41
|
+
end
|
42
|
+
|
43
|
+
def next_sibling # :nodoc:
|
44
|
+
cstruct_node_from :next
|
45
|
+
end
|
46
|
+
|
47
|
+
def previous_sibling # :nodoc:
|
48
|
+
cstruct_node_from :prev
|
49
|
+
end
|
50
|
+
|
51
|
+
def replace_with_node(new_node) # :nodoc:
|
52
|
+
LibXML.xmlReplaceNode(cstruct, new_node.cstruct)
|
53
|
+
Node.send(:relink_namespace, new_node.cstruct)
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def children # :nodoc:
|
58
|
+
return NodeSet.new(nil) if cstruct[:children].null?
|
59
|
+
child = Node.wrap(cstruct[:children])
|
60
|
+
|
61
|
+
set = NodeSet.new child.document
|
62
|
+
set_ptr = LibXML.xmlXPathNodeSetCreate(child.cstruct)
|
63
|
+
|
64
|
+
set.cstruct = LibXML::XmlNodeSet.new(set_ptr)
|
65
|
+
return set unless child
|
66
|
+
|
67
|
+
child_ptr = child.cstruct[:next]
|
68
|
+
while ! child_ptr.null?
|
69
|
+
child = Node.wrap(child_ptr)
|
70
|
+
LibXML.xmlXPathNodeSetAdd(set.cstruct, child.cstruct)
|
71
|
+
child_ptr = child.cstruct[:next]
|
72
|
+
end
|
73
|
+
|
74
|
+
return set
|
75
|
+
end
|
76
|
+
|
77
|
+
def child # :nodoc:
|
78
|
+
(val = cstruct[:children]).null? ? nil : Node.wrap(val)
|
79
|
+
end
|
80
|
+
|
81
|
+
def key?(attribute) # :nodoc:
|
82
|
+
! (prop = LibXML.xmlHasProp(cstruct, attribute.to_s)).null?
|
83
|
+
end
|
84
|
+
|
85
|
+
def namespaced_key?(attribute, namespace) # :nodoc:
|
86
|
+
prop = LibXML.xmlHasNsProp(cstruct, attribute.to_s,
|
87
|
+
namespace.nil? ? nil : namespace.to_s)
|
88
|
+
prop.null? ? false : true
|
89
|
+
end
|
90
|
+
|
91
|
+
def []=(property, value) # :nodoc:
|
92
|
+
LibXML.xmlSetProp(cstruct, property, value)
|
93
|
+
value
|
94
|
+
end
|
95
|
+
|
96
|
+
def get(attribute) # :nodoc:
|
97
|
+
return nil unless attribute
|
98
|
+
propstr = LibXML.xmlGetProp(cstruct, attribute.to_s)
|
99
|
+
return nil if propstr.null?
|
100
|
+
rval = propstr.read_string # TODO: encoding?
|
101
|
+
LibXML.xmlFree(propstr)
|
102
|
+
rval
|
103
|
+
end
|
104
|
+
|
105
|
+
def set_namespace(namespace)
|
106
|
+
LibXML.xmlSetNs(cstruct, namespace.cstruct)
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
110
|
+
def attribute(name) # :nodoc:
|
111
|
+
raise "Node#attribute not implemented yet"
|
112
|
+
end
|
113
|
+
|
114
|
+
def attribute_with_ns(name, namespace) # :nodoc:
|
115
|
+
prop = LibXML.xmlHasNsProp(cstruct, name.to_s,
|
116
|
+
namespace.nil? ? NULL : namespace.to_s)
|
117
|
+
return prop if prop.null?
|
118
|
+
Node.wrap(prop)
|
119
|
+
end
|
120
|
+
|
121
|
+
def attribute_nodes # :nodoc:
|
122
|
+
attr = []
|
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
|
130
|
+
end
|
131
|
+
|
132
|
+
def namespace # :nodoc:
|
133
|
+
cstruct[:ns].null? ? nil : Namespace.wrap(cstruct.document, cstruct[:ns])
|
134
|
+
end
|
135
|
+
|
136
|
+
def namespace_definitions # :nodoc:
|
137
|
+
list = []
|
138
|
+
ns_ptr = cstruct[:nsDef]
|
139
|
+
return list if ns_ptr.null?
|
140
|
+
while ! ns_ptr.null?
|
141
|
+
ns = Namespace.wrap(cstruct.document, ns_ptr)
|
142
|
+
list << ns
|
143
|
+
ns_ptr = ns.cstruct[:next]
|
144
|
+
end
|
145
|
+
list
|
146
|
+
end
|
147
|
+
|
148
|
+
def node_type # :nodoc:
|
149
|
+
cstruct[:type]
|
150
|
+
end
|
151
|
+
|
152
|
+
def native_content=(content) # :nodoc:
|
153
|
+
LibXML.xmlNodeSetContent(cstruct, content)
|
154
|
+
content
|
155
|
+
end
|
156
|
+
|
157
|
+
def content # :nodoc:
|
158
|
+
content_ptr = LibXML.xmlNodeGetContent(cstruct)
|
159
|
+
return nil if content_ptr.null?
|
160
|
+
content = content_ptr.read_string # TODO: encoding?
|
161
|
+
LibXML.xmlFree(content_ptr)
|
162
|
+
content
|
163
|
+
end
|
164
|
+
|
165
|
+
def add_child(child) # :nodoc:
|
166
|
+
Node.reparent_node_with(child, self) do |child_cstruct, my_cstruct|
|
167
|
+
LibXML.xmlAddChild(my_cstruct, child_cstruct)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def parent # :nodoc:
|
172
|
+
cstruct_node_from :parent
|
173
|
+
end
|
174
|
+
|
175
|
+
def node_name=(string) # :nodoc:
|
176
|
+
LibXML.xmlNodeSetName(cstruct, string)
|
177
|
+
string
|
178
|
+
end
|
179
|
+
|
180
|
+
def node_name # :nodoc:
|
181
|
+
cstruct[:name] # TODO: encoding?
|
182
|
+
end
|
183
|
+
|
184
|
+
def path # :nodoc:
|
185
|
+
path_ptr = LibXML.xmlGetNodePath(cstruct)
|
186
|
+
val = path_ptr.null? ? nil : path_ptr.read_string # TODO: encoding?
|
187
|
+
LibXML.xmlFree(path_ptr)
|
188
|
+
val
|
189
|
+
end
|
190
|
+
|
191
|
+
def add_next_sibling(next_sibling) # :nodoc:
|
192
|
+
Node.reparent_node_with(next_sibling, self) do |sibling_cstruct, my_cstruct|
|
193
|
+
LibXML.xmlAddNextSibling(my_cstruct, sibling_cstruct)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def add_previous_sibling(prev_sibling) # :nodoc:
|
198
|
+
Node.reparent_node_with(prev_sibling, self) do |sibling_cstruct, my_cstruct|
|
199
|
+
LibXML.xmlAddPrevSibling(my_cstruct, sibling_cstruct)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def native_write_to(io, encoding, indent_string, options) # :nodoc:
|
204
|
+
set_xml_indent_tree_output 1
|
205
|
+
set_xml_tree_indent_string indent_string
|
206
|
+
savectx = LibXML.xmlSaveToIO(IoCallbacks.writer(io), nil, nil, encoding, options)
|
207
|
+
LibXML.xmlSaveTree(savectx, cstruct)
|
208
|
+
LibXML.xmlSaveClose(savectx)
|
209
|
+
io
|
210
|
+
end
|
211
|
+
|
212
|
+
def line # :nodoc:
|
213
|
+
cstruct[:line]
|
214
|
+
end
|
215
|
+
|
216
|
+
def add_namespace_definition(prefix, href) # :nodoc:
|
217
|
+
ns = LibXML.xmlNewNs(cstruct, href, prefix)
|
218
|
+
LibXML.xmlSetNs(cstruct, ns) if prefix.nil?
|
219
|
+
Namespace.wrap(cstruct.document, ns)
|
220
|
+
end
|
221
|
+
|
222
|
+
def self.new(name, document, *rest) # :nodoc:
|
223
|
+
ptr = LibXML.xmlNewNode(nil, name.to_s)
|
224
|
+
|
225
|
+
node_cstruct = LibXML::XmlNode.new(ptr)
|
226
|
+
node_cstruct[:doc] = document.cstruct[:doc]
|
227
|
+
node_cstruct.keep_reference_from_document!
|
228
|
+
|
229
|
+
node = Node.wrap(node_cstruct, self)
|
230
|
+
node.send :initialize, name, document, *rest
|
231
|
+
yield node if block_given?
|
232
|
+
node
|
233
|
+
end
|
234
|
+
|
235
|
+
def dump_html # :nodoc:
|
236
|
+
return to_xml if type == DOCUMENT_NODE
|
237
|
+
buffer = LibXML::XmlBuffer.new(LibXML.xmlBufferCreate())
|
238
|
+
LibXML.htmlNodeDump(buffer, cstruct[:doc], cstruct)
|
239
|
+
buffer[:content] # TODO: encoding?
|
240
|
+
end
|
241
|
+
|
242
|
+
def compare(other) # :nodoc:
|
243
|
+
LibXML.xmlXPathCmpNodes(other.cstruct, self.cstruct)
|
244
|
+
end
|
245
|
+
|
246
|
+
def self.wrap(node_struct, klass=nil) # :nodoc:
|
247
|
+
if node_struct.is_a?(FFI::Pointer)
|
248
|
+
# cast native pointers up into a node cstruct
|
249
|
+
return nil if node_struct.null?
|
250
|
+
node_struct = LibXML::XmlNode.new(node_struct)
|
251
|
+
end
|
252
|
+
|
253
|
+
raise "wrapping a node without a document" unless node_struct.document
|
254
|
+
|
255
|
+
document_struct = node_struct.document
|
256
|
+
document = document_struct.nil? ? nil : document_struct.ruby_doc
|
257
|
+
if node_struct[:type] == DOCUMENT_NODE || node_struct[:type] == HTML_DOCUMENT_NODE
|
258
|
+
return document
|
259
|
+
end
|
260
|
+
|
261
|
+
ruby_node = node_struct.ruby_node
|
262
|
+
return ruby_node unless ruby_node.nil?
|
263
|
+
|
264
|
+
klasses = case node_struct[:type]
|
265
|
+
when ELEMENT_NODE then [XML::Element]
|
266
|
+
when TEXT_NODE then [XML::Text]
|
267
|
+
when ENTITY_REF_NODE then [XML::EntityReference]
|
268
|
+
when COMMENT_NODE then [XML::Comment]
|
269
|
+
when DOCUMENT_FRAG_NODE then [XML::DocumentFragment]
|
270
|
+
when PI_NODE then [XML::ProcessingInstruction]
|
271
|
+
when ATTRIBUTE_NODE then [XML::Attr]
|
272
|
+
when ENTITY_DECL then [XML::EntityDeclaration]
|
273
|
+
when CDATA_SECTION_NODE then [XML::CDATA]
|
274
|
+
when DTD_NODE then [XML::DTD, LibXML::XmlDtd]
|
275
|
+
else [XML::Node]
|
276
|
+
end
|
277
|
+
|
278
|
+
if klass
|
279
|
+
node = klass.allocate
|
280
|
+
else
|
281
|
+
node = klasses.first.allocate
|
282
|
+
end
|
283
|
+
node.cstruct = klasses[1] ? klasses[1].new(node_struct.pointer) : node_struct
|
284
|
+
|
285
|
+
node.cstruct.ruby_node = node
|
286
|
+
|
287
|
+
cache = document.instance_variable_get(:@node_cache)
|
288
|
+
cache << node
|
289
|
+
|
290
|
+
node.instance_variable_set(:@document, document)
|
291
|
+
document.decorate(node)
|
292
|
+
node
|
293
|
+
end
|
294
|
+
|
295
|
+
def document
|
296
|
+
cstruct.document.ruby_doc
|
297
|
+
end
|
298
|
+
|
299
|
+
private
|
300
|
+
|
301
|
+
def self.reparent_node_with(node, other, &block) # :nodoc:
|
302
|
+
raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(Nokogiri::XML::Node)
|
303
|
+
|
304
|
+
if node.cstruct[:doc] == other.cstruct[:doc]
|
305
|
+
LibXML.xmlUnlinkNode(node.cstruct)
|
306
|
+
if node.type == TEXT_NODE && other.type == TEXT_NODE && Nokogiri.is_2_6_16?
|
307
|
+
other.cstruct.pointer.put_pointer(other.cstruct.offset_of(:content), LibXML.xmlStrdup(other.cstruct[:content]))
|
308
|
+
end
|
309
|
+
reparented_struct = block.call(node.cstruct, other.cstruct)
|
310
|
+
raise(RuntimeError, "Could not reparent node (1)") unless reparented_struct
|
311
|
+
else
|
312
|
+
duped_node = LibXML.xmlDocCopyNode(node.cstruct, other.cstruct.document, 1)
|
313
|
+
raise(RuntimeError, "Could not reparent node (xmlDocCopyNode)") unless duped_node
|
314
|
+
reparented_struct = block.call(duped_node, other.cstruct)
|
315
|
+
raise(RuntimeError, "Could not reparent node (2)") unless reparented_struct
|
316
|
+
LibXML.xmlUnlinkNode(node.cstruct)
|
317
|
+
node.cstruct.keep_reference_from_document!
|
318
|
+
end
|
319
|
+
|
320
|
+
reparented_struct = LibXML::XmlNode.new(reparented_struct)
|
321
|
+
|
322
|
+
# the child was a text node that was coalesced. we need to have the object
|
323
|
+
# point at SOMETHING, or we'll totally bomb out.
|
324
|
+
if reparented_struct != node.cstruct
|
325
|
+
node.cstruct = reparented_struct
|
326
|
+
end
|
327
|
+
|
328
|
+
relink_namespace reparented_struct
|
329
|
+
|
330
|
+
reparented = Node.wrap(reparented_struct)
|
331
|
+
reparented.decorate!
|
332
|
+
reparented
|
333
|
+
end
|
334
|
+
|
335
|
+
def self.relink_namespace(reparented_struct) # :nodoc:
|
336
|
+
# Make sure that our reparented node has the correct namespaces
|
337
|
+
if reparented_struct[:doc] != reparented_struct[:parent]
|
338
|
+
LibXML.xmlSetNs(reparented_struct, LibXML::XmlNode.new(reparented_struct[:parent])[:ns])
|
339
|
+
end
|
340
|
+
|
341
|
+
# Search our parents for an existing definition
|
342
|
+
if ! reparented_struct[:nsDef].null?
|
343
|
+
ns = LibXML.xmlSearchNsByHref(
|
344
|
+
reparented_struct[:doc],
|
345
|
+
reparented_struct[:parent],
|
346
|
+
LibXML::XmlNs.new(reparented_struct[:nsDef])[:href]
|
347
|
+
)
|
348
|
+
reparented_struct[:nsDef] = nil unless ns.null?
|
349
|
+
end
|
350
|
+
|
351
|
+
# Only walk all children if there actually is a namespace we need to reparent.
|
352
|
+
return if reparented_struct[:ns].null?
|
353
|
+
|
354
|
+
# When a node gets reparented, walk it's children to make sure that
|
355
|
+
# their namespaces are reparented as well.
|
356
|
+
child_ptr = reparented_struct[:children]
|
357
|
+
while ! child_ptr.null?
|
358
|
+
child_struct = LibXML::XmlNode.new(child_ptr)
|
359
|
+
relink_namespace child_struct
|
360
|
+
child_ptr = child_struct[:next]
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
def cstruct_node_from(sym) # :nodoc:
|
365
|
+
(val = cstruct[sym]).null? ? nil : Node.wrap(val)
|
366
|
+
end
|
367
|
+
|
368
|
+
def set_xml_indent_tree_output(value) # :nodoc:
|
369
|
+
LibXML.__xmlIndentTreeOutput.write_int(value)
|
370
|
+
end
|
371
|
+
|
372
|
+
def set_xml_tree_indent_string(value) # :nodoc:
|
373
|
+
LibXML.__xmlTreeIndentString.write_pointer(LibXML.xmlStrdup(value.to_s))
|
374
|
+
end
|
375
|
+
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
class Nokogiri::XML::Element < Nokogiri::XML::Node ; end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Nokogiri
|
2
|
+
module XML
|
3
|
+
class NodeSet
|
4
|
+
|
5
|
+
attr_accessor :cstruct # :nodoc:
|
6
|
+
|
7
|
+
def dup # :nodoc:
|
8
|
+
dup = LibXML.xmlXPathNodeSetMerge(nil, self.cstruct)
|
9
|
+
NodeSet.wrap(dup)
|
10
|
+
end
|
11
|
+
|
12
|
+
def length # :nodoc:
|
13
|
+
cstruct.pointer.null? ? 0 : cstruct[:nodeNr]
|
14
|
+
end
|
15
|
+
|
16
|
+
def push(node) # :nodoc:
|
17
|
+
raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(XML::Node)
|
18
|
+
LibXML.xmlXPathNodeSetAdd(cstruct, node.cstruct)
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def +(node_set) # :nodoc:
|
23
|
+
raise(ArgumentError, "node_set must be a Nokogiri::XML::NodeSet") unless node_set.is_a?(XML::NodeSet)
|
24
|
+
new_set_ptr = LibXML::xmlXPathNodeSetMerge(nil, self.cstruct)
|
25
|
+
new_set_ptr = LibXML::xmlXPathNodeSetMerge(new_set_ptr, node_set.cstruct)
|
26
|
+
NodeSet.wrap(new_set_ptr)
|
27
|
+
end
|
28
|
+
|
29
|
+
def -(node_set) # :nodoc:
|
30
|
+
raise(ArgumentError, "node_set must be a Nokogiri::XML::NodeSet") unless node_set.is_a?(XML::NodeSet)
|
31
|
+
new_set_ptr = LibXML.xmlXPathNodeSetMerge(nil, self.cstruct)
|
32
|
+
|
33
|
+
other_nodetab = node_set.cstruct.nodeTab
|
34
|
+
node_set.cstruct[:nodeNr].times do |j|
|
35
|
+
LibXML.xmlXPathNodeSetDel(new_set_ptr, other_nodetab[j])
|
36
|
+
end
|
37
|
+
NodeSet.wrap(new_set_ptr)
|
38
|
+
end
|
39
|
+
|
40
|
+
def delete(node) # :nodoc:
|
41
|
+
raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(XML::Node)
|
42
|
+
if LibXML.xmlXPathNodeSetContains(cstruct, node.cstruct) != 0
|
43
|
+
LibXML.xmlXPathNodeSetDel(cstruct, node.cstruct)
|
44
|
+
return node
|
45
|
+
end
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def [](*args) # :nodoc:
|
50
|
+
raise(ArgumentError, "got #{args.length} arguments, expected 1 (or 2)") if args.length > 2
|
51
|
+
|
52
|
+
if args.length == 2
|
53
|
+
beg = args[0]
|
54
|
+
len = args[1]
|
55
|
+
beg += cstruct[:nodeNr] if beg < 0
|
56
|
+
return subseq(beg, len)
|
57
|
+
end
|
58
|
+
arg = args[0]
|
59
|
+
|
60
|
+
return subseq(arg.first, arg.last-arg.first+1) if arg.is_a?(Range)
|
61
|
+
|
62
|
+
index_at(arg)
|
63
|
+
end
|
64
|
+
alias_method :slice, :[]
|
65
|
+
|
66
|
+
def &(node_set) # :nodoc:
|
67
|
+
raise(ArgumentError, "node_set must be a Nokogiri::XML::NodeSet") unless node_set.is_a?(XML::NodeSet)
|
68
|
+
new_set_ptr = LibXML.xmlXPathIntersection(cstruct, node_set.cstruct)
|
69
|
+
NodeSet.wrap(new_set_ptr)
|
70
|
+
end
|
71
|
+
|
72
|
+
def include?(node) # :nodoc:
|
73
|
+
raise(ArgumentError, "node must be a Nokogiri::XML::Node") unless node.is_a?(XML::Node)
|
74
|
+
(LibXML.xmlXPathNodeSetContains(cstruct, node.cstruct) != 0) ? true : false
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_a # :nodoc:
|
78
|
+
cstruct.nodeTab.collect { |node| Node.wrap(node) }
|
79
|
+
end
|
80
|
+
|
81
|
+
def unlink # :nodoc:
|
82
|
+
# TODO: is this simpler implementation viable:
|
83
|
+
# cstruct.nodeTab.collect {|node| Node.wrap(node)}.each(&:unlink)
|
84
|
+
# ?
|
85
|
+
nodetab = cstruct.nodeTab
|
86
|
+
cstruct[:nodeNr].times do |j|
|
87
|
+
node = Node.wrap(nodetab[j])
|
88
|
+
node.unlink
|
89
|
+
nodetab[j] = node.cstruct.pointer
|
90
|
+
end
|
91
|
+
cstruct.nodeTab = nodetab
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.new document, list = [] # :nodoc:
|
96
|
+
set = NodeSet.wrap(LibXML.xmlXPathNodeSetCreate(nil))
|
97
|
+
set.document = document
|
98
|
+
list.each { |x| set << x }
|
99
|
+
yield set if block_given?
|
100
|
+
set
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def self.wrap(ptr) # :nodoc:
|
106
|
+
set = allocate
|
107
|
+
set.cstruct = LibXML::XmlNodeSet.new(ptr)
|
108
|
+
set
|
109
|
+
end
|
110
|
+
|
111
|
+
def index_at(number) # :nodoc:
|
112
|
+
return nil if (number >= cstruct[:nodeNr] || number.abs > cstruct[:nodeNr])
|
113
|
+
number = number + cstruct[:nodeNr] if number < 0
|
114
|
+
Node.wrap(cstruct.nodeAt(number))
|
115
|
+
end
|
116
|
+
|
117
|
+
def subseq(beg, len) # :nodoc:
|
118
|
+
return nil if beg > cstruct[:nodeNr]
|
119
|
+
return nil if beg < 0 || len < 0
|
120
|
+
|
121
|
+
set = NodeSet.wrap(LibXML.xmlXPathNodeSetCreate(nil))
|
122
|
+
beg.upto(beg+len-1) do |j|
|
123
|
+
LibXML.xmlXPathNodeSetAdd(set.cstruct, cstruct.nodeAt(j));
|
124
|
+
end
|
125
|
+
set
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|