libxml-ruby 0.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. data/CHANGELOG +49 -0
  2. data/LICENSE +22 -0
  3. data/README +129 -0
  4. data/Rakefile +197 -0
  5. data/TODO +84 -0
  6. data/ext/xml/cbg.c +76 -0
  7. data/ext/xml/extconf.rb +95 -0
  8. data/ext/xml/libxml.c +86 -0
  9. data/ext/xml/libxml.h +79 -0
  10. data/ext/xml/ruby_xml_attr.c +372 -0
  11. data/ext/xml/ruby_xml_attr.h +21 -0
  12. data/ext/xml/ruby_xml_attribute.c +224 -0
  13. data/ext/xml/ruby_xml_attribute.h +21 -0
  14. data/ext/xml/ruby_xml_document.c +1159 -0
  15. data/ext/xml/ruby_xml_document.h +27 -0
  16. data/ext/xml/ruby_xml_dtd.c +168 -0
  17. data/ext/xml/ruby_xml_dtd.h +17 -0
  18. data/ext/xml/ruby_xml_input_cbg.c +167 -0
  19. data/ext/xml/ruby_xml_input_cbg.h +21 -0
  20. data/ext/xml/ruby_xml_node.c +2052 -0
  21. data/ext/xml/ruby_xml_node.h +28 -0
  22. data/ext/xml/ruby_xml_node_set.c +197 -0
  23. data/ext/xml/ruby_xml_node_set.h +26 -0
  24. data/ext/xml/ruby_xml_ns.c +153 -0
  25. data/ext/xml/ruby_xml_ns.h +21 -0
  26. data/ext/xml/ruby_xml_parser.c +1363 -0
  27. data/ext/xml/ruby_xml_parser.h +31 -0
  28. data/ext/xml/ruby_xml_parser_context.c +715 -0
  29. data/ext/xml/ruby_xml_parser_context.h +22 -0
  30. data/ext/xml/ruby_xml_sax_parser.c +181 -0
  31. data/ext/xml/ruby_xml_sax_parser.h +21 -0
  32. data/ext/xml/ruby_xml_schema.c +142 -0
  33. data/ext/xml/ruby_xml_schema.h +16 -0
  34. data/ext/xml/ruby_xml_tree.c +43 -0
  35. data/ext/xml/ruby_xml_tree.h +12 -0
  36. data/ext/xml/ruby_xml_xinclude.c +20 -0
  37. data/ext/xml/ruby_xml_xinclude.h +13 -0
  38. data/ext/xml/ruby_xml_xpath.c +357 -0
  39. data/ext/xml/ruby_xml_xpath.h +24 -0
  40. data/ext/xml/ruby_xml_xpath_context.c +124 -0
  41. data/ext/xml/ruby_xml_xpath_context.h +24 -0
  42. data/ext/xml/ruby_xml_xpointer.c +100 -0
  43. data/ext/xml/ruby_xml_xpointer.h +27 -0
  44. data/ext/xml/ruby_xml_xpointer_context.c +22 -0
  45. data/ext/xml/ruby_xml_xpointer_context.h +18 -0
  46. data/tests/copy_bug.rb +21 -0
  47. data/tests/dtd-test.rb +24 -0
  48. data/tests/model/default_validation_bug.rb +0 -0
  49. data/tests/model/rubynet.xml +78 -0
  50. data/tests/model/rubynet_project +13 -0
  51. data/tests/model/xinclude.xml +5 -0
  52. data/tests/runner.rb +13 -0
  53. data/tests/schema-test.rb +74 -0
  54. data/tests/tc_default_validation.rb +0 -0
  55. data/tests/tc_xml_document.rb +51 -0
  56. data/tests/tc_xml_document_write.rb +25 -0
  57. data/tests/tc_xml_document_write2.rb +55 -0
  58. data/tests/tc_xml_document_write3.rb +97 -0
  59. data/tests/tc_xml_node.rb +59 -0
  60. data/tests/tc_xml_node2.rb +26 -0
  61. data/tests/tc_xml_node_set.rb +25 -0
  62. data/tests/tc_xml_node_xlink.rb +28 -0
  63. data/tests/tc_xml_parser.rb +175 -0
  64. data/tests/tc_xml_parser2.rb +17 -0
  65. data/tests/tc_xml_parser3.rb +23 -0
  66. data/tests/tc_xml_parser4.rb +33 -0
  67. data/tests/tc_xml_parser5.rb +27 -0
  68. data/tests/tc_xml_parser6.rb +23 -0
  69. data/tests/tc_xml_parser7.rb +28 -0
  70. data/tests/tc_xml_parser_context.rb +89 -0
  71. data/tests/tc_xml_xinclude.rb +30 -0
  72. data/tests/tc_xml_xpath.rb +23 -0
  73. data/tests/tc_xml_xpointer.rb +78 -0
  74. metadata +144 -0
data/ext/xml/cbg.c ADDED
@@ -0,0 +1,76 @@
1
+ #include <string.h>
2
+ #include <libxml/xmlIO.h>
3
+ #include "ruby.h"
4
+
5
+ /*
6
+ int xmlRegisterInputCallbacks (xmlInputMatchCallback matchFunc,
7
+ xmlInputOpenCallback openFunc,
8
+ xmlInputReadCallback readFunc,
9
+ xmlInputCloseCallback closeFunc);
10
+
11
+
12
+ int (*xmlInputMatchCallback) (char const *filename);
13
+ void* (*xmlInputOpenCallback) (char const *filename);
14
+ int (*xmlInputReadCallback) (void *context,
15
+ char *buffer,
16
+ int len);
17
+ int (*xmlInputCloseCallback) (void *context);
18
+ */
19
+
20
+ typedef struct deb_doc_context {
21
+ char *buffer;
22
+ char *bpos;
23
+ int remaining;
24
+ } deb_doc_context;
25
+
26
+ int deb_Match (char const *filename) {
27
+ fprintf( stderr, "deb_Match: %s\n", filename );
28
+ if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "deb://", 6)) {
29
+ return(1);
30
+ }
31
+ return(0);
32
+ }
33
+
34
+ void* deb_Open (char const *filename) {
35
+ deb_doc_context *deb_doc;
36
+ VALUE res;
37
+
38
+ deb_doc = (deb_doc_context*)malloc( sizeof(deb_doc_context) );
39
+
40
+ res = rb_funcall( rb_funcall( rb_mKernel, rb_intern("const_get"), 1, rb_str_new2("DEBSystem") ),
41
+ rb_intern("document_query"), 1, rb_str_new2(filename));
42
+ deb_doc->buffer = strdup( StringValuePtr(res) );
43
+ //deb_doc->buffer = strdup("<serepes>serepes</serepes>");
44
+
45
+ deb_doc->bpos = deb_doc->buffer;
46
+ deb_doc->remaining = strlen(deb_doc->buffer);
47
+ return deb_doc;
48
+ }
49
+
50
+ int deb_Read (void *context, char *buffer, int len) {
51
+ deb_doc_context *deb_doc;
52
+ int ret_len;
53
+ deb_doc = (deb_doc_context*)context;
54
+
55
+ if (len >= deb_doc->remaining) {
56
+ ret_len = deb_doc->remaining;
57
+ } else {
58
+ ret_len = len;
59
+ }
60
+ deb_doc->remaining -= ret_len;
61
+ strncpy( buffer, deb_doc->bpos, ret_len );
62
+ deb_doc->bpos += ret_len;
63
+
64
+ return ret_len;
65
+ }
66
+
67
+ int deb_Close (void *context) {
68
+ free( ((deb_doc_context*)context)->buffer );
69
+ free( context );
70
+ return 1;
71
+ }
72
+
73
+
74
+ void deb_register_cbg() {
75
+ xmlRegisterInputCallbacks( deb_Match, deb_Open, deb_Read, deb_Close );
76
+ }
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mkmf'
4
+
5
+ if defined?(CFLAGS)
6
+ if CFLAGS.index(CONFIG['CCDLFLAGS'])
7
+ $CFLAGS = CFLAGS
8
+ else
9
+ $CFLAGS = CFLAGS + ' ' + CONFIG['CCDLFLAGS']
10
+ end
11
+ else
12
+ $CFLAGS = CONFIG['CFLAGS']
13
+ end
14
+ $LDFLAGS = CONFIG['LDFLAGS']
15
+ $LIBPATH.push(Config::CONFIG['libdir'])
16
+
17
+ def crash(str)
18
+ printf(" extconf failure: %s\n", str)
19
+ exit 1
20
+ end
21
+
22
+ dir_config('iconv')
23
+ dir_config('xml2')
24
+ dir_config('zlib')
25
+
26
+ have_library('socket','socket')
27
+ have_library('nsl','gethostbyname')
28
+
29
+ unless have_library('m', 'atan')
30
+ # try again for gcc 4.0
31
+ saveflags = $CFLAGS
32
+ $CFLAGS += ' -fno-builtin'
33
+ unless have_library('m', 'atan')
34
+ crash('need libm')
35
+ end
36
+ $CFLAGS = saveflags
37
+ end
38
+
39
+ unless have_library('z', 'inflate')
40
+ crash('need zlib')
41
+ else
42
+ $defs.push('-DHAVE_ZLIB_H')
43
+ end
44
+
45
+ unless have_library('iconv','iconv_open') or have_library('c','iconv_open') or
46
+ have_library('recode','iconv_open')
47
+ crash(<<EOL)
48
+ need libiconv.
49
+
50
+ Install the libiconv or try passing one of the following options
51
+ to extconf.rb:
52
+
53
+ --with-iconv-dir=/path/to/iconv
54
+ --with-iconv-lib=/path/to/iconv/lib
55
+ --with-iconv-include=/path/to/iconv/include
56
+ EOL
57
+ end
58
+
59
+ unless have_library('xml2', 'xmlParseDoc')
60
+ crash(<<EOL)
61
+ need libxml2.
62
+
63
+ Install the library or try one of the following options to extconf.rb:
64
+
65
+ --with-xml2-dir=/path/to/libxml2
66
+ --with-xml2-lib=/path/to/libxml2/lib
67
+ --with-xml2-include=/path/to/libxml2/include
68
+ EOL
69
+ end
70
+
71
+ unless have_library('xml2', 'xmlDocFormatDump')
72
+ crash('Your version of libxml2 is too old. Please upgrade.')
73
+ end
74
+
75
+ unless have_func('docbCreateFileParserCtxt')
76
+ crash('Need docbCreateFileParserCtxt')
77
+ end
78
+
79
+ $LDFLAGS << ' ' + `xslt-config --libs`.chomp
80
+ $LDFLAGS << ' ' + `xml2-config --libs`.chomp
81
+
82
+ $CFLAGS << ' ' + `xslt-config --cflags`.chomp
83
+ $CFLAGS << ' ' + `xml2-config --cflags`.chomp
84
+ $CFLAGS = '-g -Wall ' + $CFLAGS
85
+
86
+ 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
data/ext/xml/libxml.c ADDED
@@ -0,0 +1,86 @@
1
+ /* $Id: libxml.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #include "libxml.h"
6
+
7
+ /* Ruby's util.h has ruby_strdup */
8
+ #include "util.h"
9
+
10
+ #ifdef xmlMalloc
11
+ #undef xmlMalloc
12
+ #endif
13
+ #ifdef xmlRealloc
14
+ #undef xmlRealloc
15
+ #endif
16
+ #ifdef xmlMemStrdup
17
+ #undef xmlMemStrdup
18
+ #endif
19
+ #ifdef xmlMemFree
20
+ #undef xmlMemFree
21
+ #endif
22
+
23
+ #ifdef RubyMemMalloc
24
+ #undef RubyMemMalloc
25
+ #endif
26
+ #ifdef RubyMemRealloc
27
+ #undef RubyMemRealloc
28
+ #endif
29
+ #ifdef RubyMemStrdup
30
+ #undef RubyMemStrdup
31
+ #endif
32
+ #ifdef RubyMemFree
33
+ #undef RubyMemFree
34
+ #endif
35
+
36
+ #define RubyMemFree ruby_xfree
37
+ #define RubyMemRealloc ruby_xrealloc
38
+ #define RubyMemMalloc ruby_xmalloc
39
+ #define RubyMemStrdup ruby_strdup
40
+
41
+ VALUE mXML;
42
+
43
+ static xmlFreeFunc freeFunc = NULL;
44
+ static xmlMallocFunc mallocFunc = NULL;
45
+ static xmlReallocFunc reallocFunc = NULL;
46
+ static xmlStrdupFunc strdupFunc = NULL;
47
+
48
+ void
49
+ Init_libxml(void) {
50
+ /* Some libxml memory goo that should be done before anything else */
51
+ xmlMemGet((xmlFreeFunc *) & freeFunc,
52
+ (xmlMallocFunc *) & mallocFunc,
53
+ (xmlReallocFunc *) & reallocFunc,
54
+ (xmlStrdupFunc *) & strdupFunc);
55
+
56
+ if (xmlMemSetup((xmlFreeFunc)RubyMemFree, (xmlMallocFunc)RubyMemMalloc,
57
+ (xmlReallocFunc)RubyMemRealloc, (xmlStrdupFunc)RubyMemStrdup) != 0)
58
+ rb_fatal("could not install the memory handlers for libxml");
59
+ xmlInitParser();
60
+
61
+ mXML = rb_define_module("XML");
62
+
63
+ rb_define_const(mXML, "XML_NAMESPACE", rb_str_new2((const char*)XML_XML_NAMESPACE));
64
+
65
+ ruby_init_parser();
66
+ ruby_init_xml_parser_context();
67
+ ruby_init_xml_attr();
68
+ ruby_init_xml_attribute();
69
+ ruby_init_xml_document();
70
+ ruby_init_xml_node();
71
+ ruby_init_xml_node_set();
72
+ ruby_init_xml_ns();
73
+ ruby_init_xml_sax_parser();
74
+ ruby_init_xml_tree();
75
+ ruby_init_xml_xinclude();
76
+ ruby_init_xml_xpath();
77
+ ruby_init_xml_xpath_context();
78
+ ruby_init_xml_xpointer();
79
+ ruby_init_xml_xpointer_context();
80
+ ruby_init_input_callbacks(); /* MUFF */
81
+ ruby_init_xml_dtd(); /* MUFF */
82
+ ruby_init_xml_schema(); /* MUFF */
83
+
84
+ ruby_xml_parser_default_substitute_entities_set(cXMLParser, Qtrue);
85
+ ruby_xml_parser_default_load_external_dtd_set(cXMLParser, Qtrue);
86
+ }
data/ext/xml/libxml.h ADDED
@@ -0,0 +1,79 @@
1
+ /* Please see the LICENSE file for copyright and distribution information */
2
+
3
+ #ifndef __RUBY_LIBXML_H__
4
+ #define __RUBY_LIBXML_H__
5
+
6
+ /* Don't nuke this block! It is used for automatically updating the
7
+ * versions below. VERSION = string formatting, VERNUM = numbered
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
11
+
12
+ #include <ruby.h>
13
+ #include <rubyio.h>
14
+ #include <util.h>
15
+ #include <libxml/parser.h>
16
+ #include <libxml/parserInternals.h>
17
+ #include <libxml/debugXML.h>
18
+ #include <libxml/xmlversion.h>
19
+ #include <libxml/xmlmemory.h>
20
+ #include <libxml/xpath.h>
21
+ #include <libxml/valid.h>
22
+ #include <libxml/catalog.h>
23
+ #ifdef LIBXML_DEBUG_ENABLED
24
+ #include <libxml/xpathInternals.h>
25
+ #endif
26
+ #ifdef LIBXML_XINCLUDE_ENABLED
27
+ #include <libxml/xinclude.h>
28
+ #endif
29
+ #ifdef LIBXML_XPTR_ENABLED
30
+ #include <libxml/xpointer.h>
31
+ #endif
32
+
33
+ #define RUBY_LIBXML_SRC_TYPE_NULL 0
34
+ #define RUBY_LIBXML_SRC_TYPE_FILE 1
35
+ #define RUBY_LIBXML_SRC_TYPE_STRING 2
36
+ #define RUBY_LIBXML_SRC_TYPE_IO 3
37
+ #define RUBY_LIBXML_SRC_TYPE_XPATH 4
38
+
39
+ typedef struct rx_file_data {
40
+ VALUE filename; /* Filename/path to self */
41
+ } rx_file_data;
42
+
43
+ typedef struct rx_io_data {
44
+ VALUE io;
45
+ } rx_io_data;
46
+
47
+ typedef struct rx_string_data {
48
+ VALUE str;
49
+ } rx_string_data;
50
+
51
+ typedef struct rx_xpath_data {
52
+ VALUE ctxt;
53
+ } rx_xpath_data;
54
+
55
+ #include "ruby_xml_attr.h"
56
+ #include "ruby_xml_attribute.h"
57
+ #include "ruby_xml_document.h"
58
+ #include "ruby_xml_node.h"
59
+ #include "ruby_xml_node_set.h"
60
+ #include "ruby_xml_ns.h"
61
+ #include "ruby_xml_parser.h"
62
+ #include "ruby_xml_parser_context.h"
63
+ #include "ruby_xml_sax_parser.h"
64
+ #include "ruby_xml_tree.h"
65
+ #include "ruby_xml_xinclude.h"
66
+ #include "ruby_xml_xpath.h"
67
+ #include "ruby_xml_xpath_context.h"
68
+ #include "ruby_xml_xpointer.h"
69
+ #include "ruby_xml_xpointer_context.h"
70
+ #include "ruby_xml_input_cbg.h"
71
+ #include "ruby_xml_dtd.h"
72
+ #include "ruby_xml_schema.h"
73
+
74
+ extern VALUE mXML;
75
+
76
+ void ruby_init_parser(void);
77
+ void ruby_xml_parser_free(ruby_xml_parser *rxp);
78
+
79
+ #endif
@@ -0,0 +1,372 @@
1
+ /* $Id: ruby_xml_attr.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
2
+
3
+ /* Please see the LICENSE file for copyright and distribution information */
4
+
5
+ #include "libxml.h"
6
+ #include "ruby_xml_attr.h"
7
+
8
+ VALUE cXMLAttr;
9
+
10
+ void
11
+ ruby_xml_attr_free(ruby_xml_attr *rxa) {
12
+ if (rxa->attr != NULL && !rxa->is_ptr) {
13
+ xmlUnlinkNode((xmlNodePtr)rxa->attr);
14
+ xmlFreeNode((xmlNodePtr)rxa->attr);
15
+ rxa->attr = NULL;
16
+ }
17
+
18
+ free(rxa);
19
+ }
20
+
21
+
22
+ /*
23
+ * call-seq:
24
+ * attr.child => node
25
+ *
26
+ * Obtain this attribute's child attribute(s).
27
+ */
28
+ VALUE
29
+ ruby_xml_attr_child_get(VALUE self) {
30
+ ruby_xml_attr *rxa;
31
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
32
+ if (rxa->attr->children == NULL)
33
+ return(Qnil);
34
+ else
35
+ return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attr->children));
36
+ }
37
+
38
+
39
+ /*
40
+ * call-seq:
41
+ * attr.child? => (true|false)
42
+ *
43
+ * Determine whether this attribute has child attributes.
44
+ */
45
+ VALUE
46
+ ruby_xml_attr_child_q(VALUE self) {
47
+ ruby_xml_attr *rxa;
48
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
49
+ if (rxa->attr->children == NULL)
50
+ return(Qfalse);
51
+ else
52
+ return(Qtrue);
53
+ }
54
+
55
+
56
+ /*
57
+ * call-seq:
58
+ * attr.doc => document
59
+ *
60
+ * Obtain the XML::Document this attribute is associated with,
61
+ * if any.
62
+ */
63
+ VALUE
64
+ ruby_xml_attr_doc_get(VALUE self) {
65
+ ruby_xml_attr *rxa;
66
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
67
+ if (rxa->attr->doc == NULL)
68
+ return(Qnil);
69
+ else
70
+ return(ruby_xml_document_new(cXMLDocument, rxa->attr->doc));
71
+ }
72
+
73
+
74
+ /*
75
+ * call-seq:
76
+ * attr.doc? => (true|false)
77
+ *
78
+ * Determine whether this attribute is associated with an
79
+ * XML::Document.
80
+ */
81
+ VALUE
82
+ ruby_xml_attr_doc_q(VALUE self) {
83
+ ruby_xml_attr *rxa;
84
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
85
+ if (rxa->attr->doc == NULL)
86
+ return(Qfalse);
87
+ else
88
+ return(Qtrue);
89
+ }
90
+
91
+
92
+ /*
93
+ * call-seq:
94
+ * attr.last => node
95
+ *
96
+ * Obtain the last attribute.
97
+ */
98
+ VALUE
99
+ ruby_xml_attr_last_get(VALUE self) {
100
+ ruby_xml_attr *rxa;
101
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
102
+ if (rxa->attr->last == NULL)
103
+ return(Qnil);
104
+ else
105
+ return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attr->last));
106
+ }
107
+
108
+
109
+ /*
110
+ * call-seq:
111
+ * attr.last? => (true|false)
112
+ *
113
+ * Determine whether this is the last attribute.
114
+ */
115
+ VALUE
116
+ ruby_xml_attr_last_q(VALUE self) {
117
+ ruby_xml_attr *rxa;
118
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
119
+ if (rxa->attr->last == NULL)
120
+ return(Qfalse);
121
+ else
122
+ return(Qtrue);
123
+ }
124
+
125
+
126
+ static void
127
+ ruby_xml_attr_mark(ruby_xml_attr *rxa) {
128
+ if (rxa == NULL) return;
129
+ if (!NIL_P(rxa->xd)) rb_gc_mark(rxa->xd);
130
+ }
131
+
132
+
133
+ /*
134
+ * call-seq:
135
+ * attr.name => "name"
136
+ *
137
+ * Obtain this attribute's name.
138
+ */
139
+ VALUE
140
+ ruby_xml_attr_name_get(VALUE self) {
141
+ ruby_xml_attr *rxa;
142
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
143
+
144
+ if (rxa->attr->name == NULL)
145
+ return(Qnil);
146
+ else
147
+ return(rb_str_new2((const char*)rxa->attr->name));
148
+ }
149
+
150
+
151
+ VALUE
152
+ ruby_xml_attr_new(VALUE class, VALUE xd, xmlAttrPtr attr) {
153
+ ruby_xml_attr *rxa;
154
+
155
+ rxa = ALLOC(ruby_xml_attr);
156
+ rxa->attr = attr;
157
+ rxa->xd = xd;
158
+ rxa->is_ptr = 0;
159
+ return(Data_Wrap_Struct(class, ruby_xml_attr_mark,
160
+ ruby_xml_attr_free, rxa));
161
+ }
162
+
163
+
164
+ VALUE
165
+ ruby_xml_attr_new2(VALUE class, VALUE xd, xmlAttrPtr attr) {
166
+ ruby_xml_attr *rxa;
167
+
168
+ rxa = ALLOC(ruby_xml_attr);
169
+ rxa->attr = xmlCopyProp(attr->parent, attr);
170
+ rxa->xd = xd;
171
+ rxa->is_ptr = 0;
172
+ return(Data_Wrap_Struct(class, ruby_xml_attr_mark,
173
+ ruby_xml_attr_free, rxa));
174
+ }
175
+
176
+
177
+ /*
178
+ * call-seq:
179
+ * attr.next => node
180
+ *
181
+ * Obtain the next attribute.
182
+ */
183
+ VALUE
184
+ ruby_xml_attr_next_get(VALUE self) {
185
+ ruby_xml_attr *rxa;
186
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
187
+ if (rxa->attr->next == NULL)
188
+ return(Qnil);
189
+ else
190
+ return(ruby_xml_attr_new(cXMLAttr, rxa->xd, rxa->attr->next));
191
+ }
192
+
193
+
194
+ /*
195
+ * call-seq:
196
+ * attr.next? => (true|false)
197
+ *
198
+ * Determine whether there is a next attribute.
199
+ */
200
+ VALUE
201
+ ruby_xml_attr_next_q(VALUE self) {
202
+ ruby_xml_attr *rxa;
203
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
204
+ if (rxa->attr->next == NULL)
205
+ return(Qfalse);
206
+ else
207
+ return(Qtrue);
208
+ }
209
+
210
+
211
+ /*
212
+ * call-seq:
213
+ * attr.type_name => "attribute"
214
+ *
215
+ * Obtain this attribute node's type name.
216
+ */
217
+ VALUE
218
+ ruby_xml_attr_node_type_name(VALUE self) {
219
+ /* I think libxml2's naming convention blows monkey ass */
220
+ return(rb_str_new2("attribute"));
221
+ }
222
+
223
+
224
+ /*
225
+ * call-seq:
226
+ * attr.ns => namespace
227
+ *
228
+ * Obtain this attribute's associated XML::NS, if any.
229
+ */
230
+ VALUE
231
+ ruby_xml_attr_ns_get(VALUE self) {
232
+ ruby_xml_attr *rxa;
233
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
234
+ if (rxa->attr->ns == NULL)
235
+ return(Qnil);
236
+ else
237
+ return(ruby_xml_ns_new2(cXMLNS, rxa->xd, rxa->attr->ns));
238
+ }
239
+
240
+
241
+ /*
242
+ * call-seq:
243
+ * attr.ns? => (true|false)
244
+ *
245
+ * Determine whether this attribute has an associated
246
+ * namespace.
247
+ */
248
+ VALUE
249
+ ruby_xml_attr_ns_q(VALUE self) {
250
+ ruby_xml_attr *rxa;
251
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
252
+ if (rxa->attr->ns == NULL)
253
+ return(Qfalse);
254
+ else
255
+ return(Qtrue);
256
+ }
257
+
258
+
259
+ /*
260
+ * call-seq:
261
+ * attr.parent => node
262
+ *
263
+ * Obtain this attribute node's parent.
264
+ */
265
+ VALUE
266
+ ruby_xml_attr_parent_get(VALUE self) {
267
+ ruby_xml_attr *rxa;
268
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
269
+ if (rxa->attr->parent == NULL)
270
+ return(Qnil);
271
+ else
272
+ return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attr->parent));
273
+ }
274
+
275
+
276
+ /*
277
+ * call-seq:
278
+ * attr.parent? => (true|false)
279
+ *
280
+ * Determine whether this attribute has a parent.
281
+ */
282
+ VALUE
283
+ ruby_xml_attr_parent_q(VALUE self) {
284
+ ruby_xml_attr *rxa;
285
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
286
+ if (rxa->attr->parent == NULL)
287
+ return(Qfalse);
288
+ else
289
+ return(Qtrue);
290
+ }
291
+
292
+
293
+ /*
294
+ * call-seq:
295
+ * attr.prev => node
296
+ *
297
+ * Obtain the previous attribute.
298
+ */
299
+ VALUE
300
+ ruby_xml_attr_prev_get(VALUE self) {
301
+ ruby_xml_attr *rxa;
302
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
303
+ if (rxa->attr->prev == NULL)
304
+ return(Qnil);
305
+ else
306
+ return(ruby_xml_attr_new(cXMLAttr, rxa->xd, rxa->attr->prev));
307
+ }
308
+
309
+
310
+ /*
311
+ * call-seq:
312
+ * attr.prev? => (true|false)
313
+ *
314
+ * Determine whether there is a previous attribute.
315
+ */
316
+ VALUE
317
+ ruby_xml_attr_prev_q(VALUE self) {
318
+ ruby_xml_attr *rxa;
319
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
320
+ if (rxa->attr->prev == NULL)
321
+ return(Qfalse);
322
+ else
323
+ return(Qtrue);
324
+ }
325
+
326
+
327
+ /*
328
+ * call-seq:
329
+ * attr.value => "value"
330
+ *
331
+ * Obtain the value of this attribute.
332
+ */
333
+ VALUE
334
+ ruby_xml_attr_value(VALUE self) {
335
+ ruby_xml_attr *rxa;
336
+ xmlChar *value;
337
+
338
+ Data_Get_Struct(self, ruby_xml_attr, rxa);
339
+ if (ruby_xml_attr_parent_q(self) == Qtrue) {
340
+ value = xmlGetProp(rxa->attr->parent, rxa->attr->name);
341
+ if (value != NULL)
342
+ return(rb_str_new2((const char*)value));
343
+ }
344
+ return(Qnil);
345
+ }
346
+
347
+ // Rdoc needs to know
348
+ #ifdef RDOC_NEVER_DEFINED
349
+ mXML = rb_define_module("XML");
350
+ #endif
351
+
352
+ void
353
+ ruby_init_xml_attr(void) {
354
+ cXMLAttr = rb_define_class_under(mXML, "Attr", rb_cObject);
355
+ rb_define_method(cXMLAttr, "child", ruby_xml_attr_child_get, 0);
356
+ rb_define_method(cXMLAttr, "child?", ruby_xml_attr_child_q, 0);
357
+ rb_define_method(cXMLAttr, "doc", ruby_xml_attr_doc_get, 0);
358
+ rb_define_method(cXMLAttr, "doc?", ruby_xml_attr_doc_q, 0);
359
+ rb_define_method(cXMLAttr, "last", ruby_xml_attr_last_get, 0);
360
+ rb_define_method(cXMLAttr, "last?", ruby_xml_attr_last_q, 0);
361
+ rb_define_method(cXMLAttr, "name", ruby_xml_attr_name_get, 0);
362
+ rb_define_method(cXMLAttr, "next", ruby_xml_attr_next_get, 0);
363
+ rb_define_method(cXMLAttr, "next?", ruby_xml_attr_next_q, 0);
364
+ rb_define_method(cXMLAttr, "node_type_name", ruby_xml_attr_node_type_name, 0);
365
+ rb_define_method(cXMLAttr, "ns", ruby_xml_attr_ns_get, 0);
366
+ rb_define_method(cXMLAttr, "ns?", ruby_xml_attr_ns_q, 0);
367
+ rb_define_method(cXMLAttr, "parent", ruby_xml_attr_parent_get, 0);
368
+ rb_define_method(cXMLAttr, "parent?", ruby_xml_attr_parent_q, 0);
369
+ rb_define_method(cXMLAttr, "prev", ruby_xml_attr_prev_get, 0);
370
+ rb_define_method(cXMLAttr, "prev?", ruby_xml_attr_prev_q, 0);
371
+ rb_define_method(cXMLAttr, "value", ruby_xml_attr_value, 0);
372
+ }