libxml-ruby 0.3.6 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/CHANGELOG +28 -3
  2. data/LICENSE +2 -2
  3. data/README +21 -6
  4. data/Rakefile +13 -8
  5. data/TODO +5 -12
  6. data/ext/xml/extconf.rb +17 -17
  7. data/ext/xml/libxml.c +2 -2
  8. data/ext/xml/libxml.h +5 -2
  9. data/ext/xml/libxml.rb +107 -0
  10. data/ext/xml/ruby_xml_dtd.c +3 -3
  11. data/ext/xml/ruby_xml_node.c +112 -25
  12. data/ext/xml/ruby_xml_node_set.c +61 -10
  13. data/ext/xml/ruby_xml_parser.c +62 -8
  14. data/ext/xml/ruby_xml_sax_parser.c +298 -53
  15. data/ext/xml/ruby_xml_sax_parser.h +32 -1
  16. data/ext/xml/ruby_xml_schema.c +1 -1
  17. data/ext/xml/ruby_xml_schema.h +1 -1
  18. data/ext/xml/ruby_xml_xpath.c +7 -1
  19. data/ext/xml/ruby_xml_xpath_context.c +2 -1
  20. data/ext/xml/ruby_xml_xpath_context.h +2 -2
  21. data/ext/xml/ruby_xml_xpointer_context.c +1 -2
  22. data/ext/xml/sax_parser_callbacks.inc +202 -0
  23. data/tests/copy_bug.rb +1 -2
  24. data/tests/dtd-test.rb +1 -1
  25. data/tests/libxml_test.rb +2 -0
  26. data/tests/model/saxtest.xml +5 -0
  27. data/tests/runner.rb +2 -4
  28. data/tests/schema-test.rb +1 -1
  29. data/tests/tc_xml_document.rb +2 -2
  30. data/tests/tc_xml_document_write.rb +2 -2
  31. data/tests/tc_xml_document_write2.rb +2 -2
  32. data/tests/tc_xml_document_write3.rb +2 -2
  33. data/tests/tc_xml_node.rb +2 -2
  34. data/tests/tc_xml_node2.rb +2 -2
  35. data/tests/tc_xml_node3.rb +28 -0
  36. data/tests/tc_xml_node4.rb +84 -0
  37. data/tests/tc_xml_node_set.rb +2 -2
  38. data/tests/tc_xml_node_set2.rb +38 -0
  39. data/tests/tc_xml_node_xlink.rb +2 -2
  40. data/tests/tc_xml_parser.rb +2 -2
  41. data/tests/tc_xml_parser2.rb +2 -2
  42. data/tests/tc_xml_parser3.rb +2 -2
  43. data/tests/tc_xml_parser4.rb +2 -2
  44. data/tests/tc_xml_parser5.rb +2 -2
  45. data/tests/tc_xml_parser6.rb +2 -2
  46. data/tests/tc_xml_parser7.rb +2 -2
  47. data/tests/tc_xml_parser8.rb +32 -0
  48. data/tests/tc_xml_parser_context.rb +2 -2
  49. data/tests/tc_xml_xinclude.rb +2 -2
  50. data/tests/tc_xml_xpath.rb +3 -2
  51. data/tests/tc_xml_xpointer.rb +3 -2
  52. data/tests/test_xml_sax_parser.rb +64 -0
  53. metadata +13 -6
  54. data/tests/tc_default_validation.rb +0 -0
data/CHANGELOG CHANGED
@@ -1,14 +1,39 @@
1
- ===== 21.2.2006 Ross Bamford <rosco@roscopeco.co.uk>
1
+ ===== 15.4.2006 Ross Bamford <rosco at roscopeco.co.uk>
2
+ * Implemented SAX parser callback handling
3
+
4
+ ===== 12.4.2006 Ross Bamford <rosco at roscopeco.co.uk>
5
+ * Integrated / tested community patches
6
+ * Defined XML::Node (hash) equality in terms of XML representation
7
+
8
+ ===== 12.4.2006 Tim Yamin <plasmaroo at gentoo.org> (patches)
9
+ * Fixed XML::Node#content inoperable bug
10
+ * Fixed memory leak in same
11
+
12
+ ===== 12.4.2006 Mark Van Holstyn <mvette13 at gmail.com> (patches)
13
+ * Added XML::Node::Set#first
14
+ * Added XML::Node::Set#empty?
15
+ * Fixes to XML::Node::Set#to_a
16
+ * Added XML::Node#find_first
17
+ * Added XML::Node#remove!
18
+
19
+ ===== 27.3.2006 Ross Bamford <rosco at roscopeco.co.uk>
20
+ * Integrated contributed XML::Parser.register_error_handler patch
21
+
22
+ ===== 27.2.2006 Ross Bamford <rosco at roscopeco.co.uk>
23
+ * Fixed all multiple symbol definitions for -fno-common.
24
+ * Removed OSX -fno-common workaround.
25
+
26
+ ===== 21.2.2006 Ross Bamford <rosco at roscopeco.co.uk>
2
27
  * Patched extconf.rb with OSX -fno-common workaround
3
28
  * Added gem and packaging support to Rakefile
4
29
  * Moved version update to Rakefile
5
30
  * Removed legacy project utility scripts
6
31
 
7
- ===== 19.2.2006 Ross Bamford <rosco@roscopeco.co.uk>
32
+ ===== 19.2.2006 Ross Bamford <rosco at roscopeco.co.uk>
8
33
  * Fixed doublefree bug in ruby_xml_attr.
9
34
  * Fixed small leak in parser
10
35
 
11
- ===== 18.12.2005 Ross Bamford <rosco@roscopeco.co.uk>
36
+ ===== 18.12.2005 Ross Bamford <rosco at roscopeco.co.uk>
12
37
  * Updated for GCC 4.0 (community patches)
13
38
  * Fixed default validation bug
14
39
  * Refactored project, removed outdated files, cleaned up tests.
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
- # $Id: LICENSE,v 1.2 2005/12/29 19:00:01 bshow Exp $
1
+ # $Id: LICENSE,v 1.3 2006/02/28 09:57:52 roscopeco Exp $
2
2
 
3
- Copyright (c) 2002-2005 Sean Chittenden <sean@chittenden.org> and contributors
3
+ Copyright (c) 2002-2006 Sean Chittenden <sean@chittenden.org> and contributors
4
4
  Copyright (c) 2001 Wai-Sun "Squidster" Chia <waisun.chia@compaq.com>
5
5
 
6
6
  Permission is hereby granted, free of charge, to any person obtaining a copy of
data/README CHANGED
@@ -2,13 +2,25 @@
2
2
 
3
3
  Installation is simple. Follow the following steps:
4
4
 
5
- $ ruby extconf.rb
6
- $ make
7
- # make install
5
+ === Rubygems
6
+
7
+ gem install libxml-ruby
8
+
9
+ === Tarball/zip
10
+
11
+ $ rake test
12
+ $ rake install
8
13
 
9
14
  If extconf yacks up an error, follow the instructions it provides.
10
- Once installed, look at the test scripts (*.rb, not extconf.rb) and
11
- make sure you run document_self.rb to see what's available.
15
+ You will need to chdir to ext/xml and run 'ruby extconf.rb' to provide
16
+ options, after which you can either use Rake for everything or
17
+ do with make (make && make install).
18
+
19
+ Once installed, look at the test scripts (tests/*.rb), and run
20
+ 'rake doc' to generate API documentation.
21
+ You can find the latest documentation at:
22
+
23
+ * http://libxml.rubyforge.org/doc
12
24
 
13
25
  == DEPENDENCIES
14
26
 
@@ -28,7 +40,9 @@ Basic usage for reading and writing documents.
28
40
 
29
41
  Writing a simple document:
30
42
 
43
+ # require 'rubygems' # if installed via Gems
31
44
  require 'xml/libxml'
45
+
32
46
  doc = XML::Document.new()
33
47
  doc.root = XML::Node.new('root_node')
34
48
  root = doc.root
@@ -94,6 +108,7 @@ perform this operation. This reads in and processes the above
94
108
  generated XML document, output.xml. This script assumes that the
95
109
  structure of the document is already known.
96
110
 
111
+ # require 'rubygems' # if installed via Gems
97
112
  require 'xml/libxml'
98
113
  doc = XML::Document.file('output.xml')
99
114
  root = doc.root
@@ -126,4 +141,4 @@ And your terminal should look like:
126
141
 
127
142
  If you have any questions, please send email to libxml-devel@rubyforge.org.
128
143
 
129
- # $Id: README,v 1.2 2005/12/19 20:51:39 roscopeco Exp $
144
+ # $Id: README,v 1.5 2006/04/24 19:29:49 roscopeco Exp $
data/Rakefile CHANGED
@@ -71,14 +71,14 @@ task :test => :unittests
71
71
 
72
72
  Rake::TestTask.new(:alltests) do |t|
73
73
  t.test_files = FileList[
74
- 'tests/tc_*.rb',
74
+ 'tests/runner.rb',
75
75
  'tests/contrib/*.rb',
76
76
  ]
77
77
  t.verbose = true
78
78
  end
79
79
 
80
80
  Rake::TestTask.new(:unittests) do |t|
81
- t.test_files = FileList['tests/tc_*.rb']
81
+ t.test_files = FileList['tests/runner.rb']
82
82
  t.verbose = false
83
83
  end
84
84
 
@@ -98,7 +98,8 @@ rd = Rake::RDocTask.new(:doc) do |rdoc|
98
98
  rdoc.title = "Libxml-Ruby API"
99
99
  rdoc.options << '--main' << 'README'
100
100
  rdoc.rdoc_files.include('README', 'LICENSE', 'TODO')
101
- rdoc.rdoc_files.include('ext/xml/ruby_xml*.c', '*.rdoc')
101
+ rdoc.rdoc_files.include('ext/xml/ruby_xml*.c', 'ext/xml/*.rb')
102
+ rdoc.rdoc_files.include('*.rdoc')
102
103
  end
103
104
 
104
105
  desc "Publish the RDoc documentation to project web site"
@@ -119,9 +120,13 @@ end
119
120
  task :update_version do
120
121
  unless PKG_VERSION == CURRENT_VERSION
121
122
  File.open('ext/xml/libxml.h.new','w+') do |f|
123
+ maj, min, mic = /(\d+)\.(\d+)(?:\.(\d+))?/.match(PKG_VERSION).captures
122
124
  f << File.read('ext/xml/libxml.h').
123
125
  gsub(/RUBY_LIBXML_VERSION\s+"(\d.+)"/) { "RUBY_LIBXML_VERSION \"#{PKG_VERSION}\"" }.
124
- gsub(/RUBY_LIBXML_VERNUM\s+\d+/) { "RUBY_LIBXML_VERNUM #{PKG_VERSION.tr('.','')}" }
126
+ gsub(/RUBY_LIBXML_VERNUM\s+\d+/) { "RUBY_LIBXML_VERNUM #{PKG_VERSION.tr('.','').sub(/^0*/,'')}" }.
127
+ gsub(/RUBY_LIBXML_VER_MAJ\s+\d+/) { "RUBY_LIBXML_VER_MAJ #{maj}" }.
128
+ gsub(/RUBY_LIBXML_VER_MIN\s+\d+/) { "RUBY_LIBXML_VER_MIN #{min}" }.
129
+ gsub(/RUBY_LIBXML_VER_MIC\s+\d+/) { "RUBY_LIBXML_VER_MIC #{mic || 0}" }
125
130
  end
126
131
  mv('ext/xml/libxml.h.new', 'ext/xml/libxml.h')
127
132
  end
@@ -130,7 +135,8 @@ end
130
135
  PKG_FILES = FileList[
131
136
  'ext/xml/extconf.rb',
132
137
  '[A-Z]*',
133
- 'ext/xml/*.c',
138
+ 'ext/xml/*.c',
139
+ 'ext/xml/*.inc',
134
140
  'ext/xml/ruby_xml*.h',
135
141
  'ext/xml/libxml.h',
136
142
  'tests/**/*',
@@ -161,11 +167,10 @@ else
161
167
 
162
168
  #### Documentation and testing.
163
169
  s.has_rdoc = true
164
- s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$/ }.to_a
170
+ s.extra_rdoc_files = rd.rdoc_files.to_a
165
171
  s.rdoc_options <<
166
172
  '--title' << 'Libxml-Ruby API' <<
167
- '--main' << 'README' <<
168
- '-o' << 'rdoc'
173
+ '--main' << 'README'
169
174
 
170
175
  s.test_files = Dir.glob('tests/*runner.rb')
171
176
 
data/TODO CHANGED
@@ -1,19 +1,10 @@
1
- $Id: TODO,v 1.1 2005/12/19 19:53:07 roscopeco Exp $
1
+ $Id: TODO,v 1.4 2006/04/12 12:08:39 roscopeco Exp $
2
2
 
3
3
  ==== BUGS
4
4
 
5
- * Hunt down a 4-8KB/s leak while running rubytest -i0 -F on the library.
6
-
7
- * Also some other C-side problems:
8
- * doublefree at Ruby exit when copying nodes between documents,
9
- and using node sets, sample trace in node_set_bug.txt
10
- * XML::Attr.name gives [BUG] segfault line.
11
-
12
5
  * Some C funcs need more NULL checking, they're throwing wierd
13
6
  ArgumentErrors into RubyLand. See TODOs in source.
14
7
 
15
- * Get libxml to compile and build with OS-X.
16
-
17
8
  ==== ENHANCEMENTS
18
9
 
19
10
  * Add warnings to each of the xpath functions if xpath isn't compiled
@@ -51,8 +42,6 @@ $Id: TODO,v 1.1 2005/12/19 19:53:07 roscopeco Exp $
51
42
  'return(Qnil)' with exceptions if 'return(Qnil)' is being used for
52
43
  signaling an error or inability to process the document.
53
44
 
54
- * Pointer target signedness warnings (GCC 4.0)
55
-
56
45
  * Need to add the ability to create namespace objects and modify them
57
46
  accordingly.
58
47
 
@@ -78,6 +67,10 @@ $Id: TODO,v 1.1 2005/12/19 19:53:07 roscopeco Exp $
78
67
 
79
68
  * Add ability to append hashes and arrays via the XML::Node#<< method.
80
69
 
70
+ * Node (etc.) #[] should support symbol keys.
71
+
72
+ * Make nodes comparable (on qualified name?)
73
+
81
74
  ==== Data Serialization
82
75
 
83
76
  * Need to define DTD for basic ruby types that have been XML serialized
@@ -42,8 +42,10 @@ else
42
42
  $defs.push('-DHAVE_ZLIB_H')
43
43
  end
44
44
 
45
- unless have_library('iconv','iconv_open') or have_library('c','iconv_open') or
46
- have_library('recode','iconv_open')
45
+ unless have_library('iconv','iconv_open') or
46
+ have_library('c','iconv_open') or
47
+ have_library('recode','iconv_open') or
48
+ have_library('iconv')
47
49
  crash(<<EOL)
48
50
  need libiconv.
49
51
 
@@ -56,7 +58,13 @@ need libiconv.
56
58
  EOL
57
59
  end
58
60
 
59
- unless have_library('xml2', 'xmlParseDoc')
61
+ unless (have_library('xml2', 'xmlParseDoc') or
62
+ find_library('xml2', '/opt/lib', '/usr/local/lib', '/usr/lib')) and
63
+ (have_header('libxml/xmlversion.h') or
64
+ find_header('libxml/xmlversion.h',
65
+ '/opt/include/libxml2',
66
+ '/usr/local/include/libxml2',
67
+ '/usr/include/libxml2'))
60
68
  crash(<<EOL)
61
69
  need libxml2.
62
70
 
@@ -76,20 +84,12 @@ unless have_func('docbCreateFileParserCtxt')
76
84
  crash('Need docbCreateFileParserCtxt')
77
85
  end
78
86
 
79
- $LDFLAGS << ' ' + `xslt-config --libs`.chomp
80
- $LDFLAGS << ' ' + `xml2-config --libs`.chomp
87
+ if try_compile('int main() { return 0; }','-Wall')
88
+ $CFLAGS << ' -Wall'
89
+ end
81
90
 
82
- $CFLAGS << ' ' + `xslt-config --cflags`.chomp
83
- $CFLAGS << ' ' + `xml2-config --cflags`.chomp
84
- $CFLAGS = '-g -Wall ' + $CFLAGS
91
+ $CFLAGS << ' ' << $INCFLAGS
92
+ $INSTALLFILES = [["../xml/libxml.rb", "$(RUBYLIBDIR)", "../xml"]]
85
93
 
86
94
  create_header()
87
- create_makefile('xml/libxml')
88
-
89
- # Quick hack around a problem building on OSX
90
- if RUBY_PLATFORM =~ /darwin/
91
- mf = File.read('Makefile')
92
- File.open('Makefile','w+') do |f|
93
- f << mf.gsub(/^CFLAGS\s+=\s+(.*)/) { "CFLAGS = #{$1.gsub('-fno-common','')}" }
94
- end
95
- end
95
+ create_makefile('xml/libxml_so')
@@ -1,4 +1,4 @@
1
- /* $Id: libxml.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
1
+ /* $Id: libxml.c,v 1.2 2006/04/17 13:30:22 roscopeco Exp $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -46,7 +46,7 @@ static xmlReallocFunc reallocFunc = NULL;
46
46
  static xmlStrdupFunc strdupFunc = NULL;
47
47
 
48
48
  void
49
- Init_libxml(void) {
49
+ Init_libxml_so(void) {
50
50
  /* Some libxml memory goo that should be done before anything else */
51
51
  xmlMemGet((xmlFreeFunc *) & freeFunc,
52
52
  (xmlMallocFunc *) & mallocFunc,
@@ -6,8 +6,11 @@
6
6
  /* Don't nuke this block! It is used for automatically updating the
7
7
  * versions below. VERSION = string formatting, VERNUM = numbered
8
8
  * version for inline testing: increment both or none at all. */
9
- #define RUBY_LIBXML_VERSION "0.3.6"
10
- #define RUBY_LIBXML_VERNUM 036
9
+ #define RUBY_LIBXML_VERSION "0.3.8"
10
+ #define RUBY_LIBXML_VERNUM 38
11
+ #define RUBY_LIBXML_VER_MAJ 0
12
+ #define RUBY_LIBXML_VER_MIN 3
13
+ #define RUBY_LIBXML_VER_MIC 8
11
14
 
12
15
  #include <ruby.h>
13
16
  #include <rubyio.h>
@@ -0,0 +1,107 @@
1
+ # $Id: libxml.rb,v 1.1 2006/04/17 13:30:22 roscopeco Exp $
2
+ # Please see the LICENSE file for copyright and distribution information
3
+ require 'xml/libxml_so'
4
+
5
+ class XML::Node::Set
6
+ def empty? #:nodoc:
7
+ self.length <= 0
8
+ end
9
+
10
+ def first #:nodoc:
11
+ self.each { |n| return n }
12
+ end
13
+ end
14
+
15
+ class XML::Document
16
+ include Enumerable
17
+
18
+ # maybe, maybe not...
19
+ def each(&blk) #:nodoc:
20
+ find('//*').each(&blk)
21
+ end
22
+ end
23
+
24
+ class XML::Node::Set
25
+ # inefficient, but maybe can find a way to cache the
26
+ # ary and dump on change?
27
+ def [](i, count = nil) #:nodoc:
28
+ if count
29
+ to_a[i,count]
30
+ else
31
+ to_a[i]
32
+ end
33
+ end
34
+
35
+ def to_s #:nodoc:
36
+ to_a.to_s
37
+ end
38
+ end
39
+
40
+ module XML::SiblingEnum #:nodoc:all
41
+ private
42
+
43
+ # Iterates nodes and attributes
44
+ def siblings(node, &blk)
45
+ if n = node
46
+ loop do
47
+ blk.call(n)
48
+ break unless n = n.next
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ class XML::Node
55
+ include XML::SiblingEnum
56
+ include Enumerable
57
+ include Comparable
58
+
59
+ # maybe these don't belong on all nodes...
60
+ def each_child(&blk) #:nodoc:
61
+ siblings(child, &blk)
62
+ end
63
+
64
+ def each_attr(&blk) #:nodoc:
65
+ siblings(properties, &blk)
66
+ end
67
+
68
+ # all siblings INCLUDING self
69
+ def each_sibling(&blk) #:nodoc:
70
+ siblings(self, &blk)
71
+ end
72
+
73
+ # I guess this is what you'd expect?
74
+ alias :each :each_child
75
+
76
+ def to_a #:nodoc:
77
+ inject([]) { |ary,n| ary << n }
78
+ end
79
+
80
+ def <=>(other) #:nodoc:
81
+ to_s <=> other.to_s
82
+ end
83
+ end
84
+
85
+ class XML::Attr
86
+ include XML::SiblingEnum
87
+ include Enumerable
88
+
89
+ def each_sibling(&blk) #:nodoc:
90
+ siblings(self,&blk)
91
+ end
92
+
93
+ alias :each_attr :each_sibling
94
+ alias :each :each_sibling
95
+
96
+ def to_h #:nodoc:
97
+ inject({}) do |h,a| h[a.name] = a.value end
98
+ end
99
+
100
+ def to_a #:nodoc:
101
+ inject([]) do |ary,a| ary << [a.name, a.value] end
102
+ end
103
+
104
+ def to_s #:nodoc:
105
+ "#{name} = #{value}"
106
+ end
107
+ end
@@ -22,10 +22,10 @@ ruby_xml_dtd_mark(ruby_xml_dtd *rxdtd) {
22
22
 
23
23
  /*
24
24
  * call-seq:
25
- * XML::DTD.new("public system") => dtd
26
- * XML::DTD.new("public", "system") => dtd
25
+ * XML::Dtd.new("public system") => dtd
26
+ * XML::Dtd.new("public", "system") => dtd
27
27
  *
28
- * Create a new DTD from the specified public and system
28
+ * Create a new Dtd from the specified public and system
29
29
  * identifiers.
30
30
  */
31
31
  VALUE
@@ -1,4 +1,4 @@
1
- /* $Id: ruby_xml_node.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
1
+ /* $Id: ruby_xml_node.c,v 1.3 2006/04/12 12:08:39 roscopeco Exp $ */
2
2
 
3
3
  /* Please see the LICENSE file for copyright and distribution information */
4
4
 
@@ -141,7 +141,7 @@ ruby_xml_node_content_add(VALUE self, VALUE obj) {
141
141
  } else {
142
142
  str = rb_obj_as_string(obj);
143
143
  if (NIL_P(str) || TYPE(str) != T_STRING)
144
- rb_raise(rb_eTypeError, "invalid argumnt: must be string or XML::Node");
144
+ rb_raise(rb_eTypeError, "invalid argument: must be string or XML::Node");
145
145
 
146
146
  xmlNodeAddContent(node->node, (xmlChar*)StringValuePtr(str));
147
147
  return(obj);
@@ -158,24 +158,17 @@ ruby_xml_node_content_add(VALUE self, VALUE obj) {
158
158
  VALUE
159
159
  ruby_xml_node_content_get(VALUE self) {
160
160
  ruby_xml_node *rxn;
161
-
161
+ xmlChar *content;
162
+ VALUE out;
163
+
162
164
  Data_Get_Struct(self, ruby_xml_node, rxn);
163
- if (rxn->node->type == XML_ELEMENT_NODE || rxn->node->content == NULL)
164
- return(Qnil);
165
- else {
166
- return(rb_str_new2((const char*)rxn->node->content));
167
- }
165
+ content = xmlNodeGetContent(rxn->node);
166
+ out = rb_str_new2((const char *) content);
167
+ xmlFree(content);
168
+
169
+ return out;
168
170
  }
169
171
 
170
- /////////////////////////////////////////////
171
- // TODO may be bugged:
172
- //
173
- // node.content = "123"
174
- // node.content => nil
175
- // node.content_stripped => nil
176
- // node.to_s => "<head xml:base=\"123\">wow</head>"
177
-
178
-
179
172
  /*
180
173
  * call-seq:
181
174
  * node.content = "string"
@@ -193,15 +186,14 @@ ruby_xml_node_content_set(VALUE self, VALUE content) {
193
186
  }
194
187
 
195
188
 
196
- /////////////////////////////////////////////////////
197
- // TODO may be bugged: see above
198
- //
199
-
200
189
  /*
201
190
  * call-seq:
202
191
  * node.content_stripped => "string"
203
192
  *
204
193
  * Obtain this node's stripped content.
194
+ *
195
+ * *Deprecated*: Stripped content can be obtained via the
196
+ * +content+ method.
205
197
  */
206
198
  VALUE
207
199
  ruby_xml_node_content_stripped_get(VALUE self) {
@@ -584,6 +576,28 @@ ruby_xml_node_entity_ref_q(VALUE self) {
584
576
  return(Qfalse);
585
577
  }
586
578
 
579
+ VALUE ruby_xml_node_to_s(VALUE self);
580
+
581
+ /*
582
+ * call-seq:
583
+ * node.eql?(other_node) => (true|false)
584
+ *
585
+ * Test equality between the two nodes. Equality is determined based
586
+ * on the XML representation of the nodes.
587
+ */
588
+ VALUE
589
+ ruby_xml_node_eql_q(VALUE self, VALUE other) {
590
+ // TODO this isn't the best way to handle this
591
+ ruby_xml_node *rxn, *orxn;
592
+ VALUE thisxml, otherxml;
593
+ Data_Get_Struct(self, ruby_xml_node, rxn);
594
+ Data_Get_Struct(other, ruby_xml_node, orxn);
595
+ thisxml = ruby_xml_node_to_s(self);
596
+ otherxml = ruby_xml_node_to_s(other);
597
+
598
+ return(rb_funcall(thisxml, rb_intern("=="), 1, otherxml));
599
+ }
600
+
587
601
 
588
602
  /*
589
603
  * call-seq:
@@ -609,6 +623,34 @@ ruby_xml_node_find(int argc, VALUE *argv, VALUE self) {
609
623
  return(ruby_xml_xpath_find2(vargc, vargv));
610
624
  }
611
625
 
626
+ /*
627
+ * call-seq:
628
+ * node.find_first(xpath_expr, namespace = [any]) => nodeset
629
+ *
630
+ * Find the first node matching the specified xpath expression, optionally
631
+ * using the specified namespaces. Returns an XML::Node.
632
+ */
633
+ VALUE
634
+ ruby_xml_node_find_first(int argc, VALUE *argv, VALUE self) {
635
+ VALUE ns = ruby_xml_node_find(argc, argv, self);
636
+ ruby_xml_node_set *rxnset;
637
+
638
+ Data_Get_Struct(ns, ruby_xml_node_set, rxnset);
639
+ if (rxnset->node_set == NULL || rxnset->node_set->nodeNr < 1)
640
+ return(Qnil);
641
+
642
+ VALUE nodeobj;
643
+ switch(rxnset->node_set->nodeTab[0]->type) {
644
+ case XML_ATTRIBUTE_NODE:
645
+ nodeobj = ruby_xml_attr_new2(cXMLAttr, rxnset->xd, (xmlAttrPtr)rxnset->node_set->nodeTab[0]);
646
+ break;
647
+ default:
648
+ nodeobj = ruby_xml_node_new2(cXMLNode, rxnset->xd, rxnset->node_set->nodeTab[0]);
649
+ }
650
+
651
+ return(nodeobj);
652
+ }
653
+
612
654
 
613
655
  /*
614
656
  * call-seq:
@@ -638,6 +680,24 @@ void ruby_xml_node_free(ruby_xml_node *rxn) {
638
680
  }
639
681
 
640
682
 
683
+ /*
684
+ * call-seq:
685
+ * node.hash => fixnum
686
+ *
687
+ * Returns the hash-code for this node. This is the hash of the XML
688
+ * representation in order to be consistent with eql.
689
+ */
690
+ VALUE
691
+ ruby_xml_node_hash(VALUE self) {
692
+ ruby_xml_node *rxn;
693
+ VALUE thisxml;
694
+ Data_Get_Struct(self, ruby_xml_node, rxn);
695
+ thisxml = ruby_xml_node_to_s(self);
696
+
697
+ return(rb_funcall(thisxml, rb_intern("hash"), 0));
698
+ }
699
+
700
+
641
701
  /*
642
702
  * call-seq:
643
703
  * node.html_doc? => (true|false)
@@ -1599,10 +1659,17 @@ ruby_xml_node_property_set(VALUE self, VALUE key, VALUE val) {
1599
1659
  xmlAttrPtr attr;
1600
1660
  VALUE rattr;
1601
1661
 
1602
- Check_Type(key, T_STRING);
1603
- Check_Type(val, T_STRING);
1604
1662
  Data_Get_Struct(self, ruby_xml_node, node);
1605
-
1663
+ Check_Type(key, T_STRING);
1664
+
1665
+ if( val == Qnil ) {
1666
+ attr = xmlSetProp(node->node, (xmlChar*)StringValuePtr(key), NULL);
1667
+ xmlRemoveProp( attr );
1668
+ return Qnil;
1669
+ } else {
1670
+ Check_Type(val, T_STRING);
1671
+ }
1672
+
1606
1673
  attr = xmlSetProp(node->node, (xmlChar*)StringValuePtr(key), (xmlChar*)StringValuePtr(val));
1607
1674
  if (attr == NULL) {
1608
1675
  attr = xmlNewProp(node->node, (xmlChar*)StringValuePtr(key), (xmlChar*)StringValuePtr(val));
@@ -1656,6 +1723,21 @@ ruby_xml_node_properties_q(VALUE self) {
1656
1723
  }
1657
1724
 
1658
1725
 
1726
+ /*
1727
+ * call-seq:
1728
+ * node.remove! => nil
1729
+ *
1730
+ * Removes this node from it's parent.
1731
+ */
1732
+ VALUE
1733
+ ruby_xml_node_remove_ex(VALUE self) {
1734
+ ruby_xml_node *rxn;
1735
+ Data_Get_Struct(self, ruby_xml_node, rxn);
1736
+ xmlUnlinkNode(rxn->node);
1737
+ return(Qnil);
1738
+ }
1739
+
1740
+
1659
1741
  /*
1660
1742
  * call-seq:
1661
1743
  * node.search_href => namespace
@@ -1800,7 +1882,6 @@ ruby_xml_node_to_s(VALUE self) {
1800
1882
  buf = xmlBufferCreate();
1801
1883
  xmlNodeDump(buf, rxn->node->doc, rxn->node, 0, 1);
1802
1884
  result = rb_str_new2((const char*)buf->content);
1803
- // TODO result = rb_str_new2((const char*)buf->content); ?
1804
1885
 
1805
1886
  xmlBufferFree(buf);
1806
1887
  return result;
@@ -2004,8 +2085,11 @@ ruby_init_xml_node(void) {
2004
2085
  rb_define_method(cXMLNode, "empty?", ruby_xml_node_empty_q, 0);
2005
2086
  rb_define_method(cXMLNode, "entity?", ruby_xml_node_entity_q, 0);
2006
2087
  rb_define_method(cXMLNode, "entity_ref?", ruby_xml_node_entity_ref_q, 0);
2088
+ rb_define_method(cXMLNode, "eql?", ruby_xml_node_eql_q, 1);
2007
2089
  rb_define_method(cXMLNode, "find", ruby_xml_node_find, -1);
2090
+ rb_define_method(cXMLNode, "find_first", ruby_xml_node_find_first, -1);
2008
2091
  rb_define_method(cXMLNode, "fragment?", ruby_xml_node_fragment_q, 0);
2092
+ rb_define_method(cXMLNode, "hash", ruby_xml_node_hash, 0);
2009
2093
  rb_define_method(cXMLNode, "html_doc?", ruby_xml_node_html_doc_q, 0);
2010
2094
  rb_define_method(cXMLNode, "lang", ruby_xml_node_lang_get, 0);
2011
2095
  rb_define_method(cXMLNode, "lang=", ruby_xml_node_lang_set, 1);
@@ -2037,6 +2121,7 @@ ruby_init_xml_node(void) {
2037
2121
  rb_define_method(cXMLNode, "property", ruby_xml_node_property_get, 1);
2038
2122
  rb_define_method(cXMLNode, "properties", ruby_xml_node_properties_get, 0);
2039
2123
  rb_define_method(cXMLNode, "properties?", ruby_xml_node_properties_q, 0);
2124
+ rb_define_method(cXMLNode, "remove!", ruby_xml_node_remove_ex, 0);
2040
2125
  rb_define_method(cXMLNode, "search_ns", ruby_xml_node_search_ns, 1);
2041
2126
  rb_define_method(cXMLNode, "search_href", ruby_xml_node_search_href, 1);
2042
2127
  rb_define_method(cXMLNode, "sibling=", ruby_xml_node_sibling_set, 1);
@@ -2049,4 +2134,6 @@ ruby_init_xml_node(void) {
2049
2134
  rb_define_method(cXMLNode, "xlink?", ruby_xml_node_xlink_q, 0);
2050
2135
  rb_define_method(cXMLNode, "xlink_type", ruby_xml_node_xlink_type, 0);
2051
2136
  rb_define_method(cXMLNode, "xlink_type_name", ruby_xml_node_xlink_type_name, 0);
2137
+
2138
+ rb_define_alias(cXMLNode, "==", "eql?");
2052
2139
  }