[Pkg-ruby-extras-maintainers] r964 - in packages-wip/libxml-ruby/trunk: . debian

Filipe Lautert filipe-guest at alioth.debian.org
Fri Nov 3 22:04:09 CET 2006


Author: filipe-guest
Date: 2006-11-03 22:04:08 +0100 (Fri, 03 Nov 2006)
New Revision: 964

Added:
   packages-wip/libxml-ruby/trunk/cbg.c
   packages-wip/libxml-ruby/trunk/debian/
   packages-wip/libxml-ruby/trunk/debian/changelog
   packages-wip/libxml-ruby/trunk/debian/compat
   packages-wip/libxml-ruby/trunk/debian/control
   packages-wip/libxml-ruby/trunk/debian/control.in
   packages-wip/libxml-ruby/trunk/debian/copyright
   packages-wip/libxml-ruby/trunk/debian/docs
   packages-wip/libxml-ruby/trunk/debian/rules
   packages-wip/libxml-ruby/trunk/debian/watch
   packages-wip/libxml-ruby/trunk/extconf.rb
   packages-wip/libxml-ruby/trunk/libxml.c
   packages-wip/libxml-ruby/trunk/libxml.h
   packages-wip/libxml-ruby/trunk/libxml.rb
   packages-wip/libxml-ruby/trunk/ruby_xml_attr.c
   packages-wip/libxml-ruby/trunk/ruby_xml_attr.h
   packages-wip/libxml-ruby/trunk/ruby_xml_attribute.c
   packages-wip/libxml-ruby/trunk/ruby_xml_attribute.h
   packages-wip/libxml-ruby/trunk/ruby_xml_document.c
   packages-wip/libxml-ruby/trunk/ruby_xml_document.h
   packages-wip/libxml-ruby/trunk/ruby_xml_dtd.c
   packages-wip/libxml-ruby/trunk/ruby_xml_dtd.h
   packages-wip/libxml-ruby/trunk/ruby_xml_input_cbg.c
   packages-wip/libxml-ruby/trunk/ruby_xml_input_cbg.h
   packages-wip/libxml-ruby/trunk/ruby_xml_node.c
   packages-wip/libxml-ruby/trunk/ruby_xml_node.h
   packages-wip/libxml-ruby/trunk/ruby_xml_node_set.c
   packages-wip/libxml-ruby/trunk/ruby_xml_node_set.h
   packages-wip/libxml-ruby/trunk/ruby_xml_ns.c
   packages-wip/libxml-ruby/trunk/ruby_xml_ns.h
   packages-wip/libxml-ruby/trunk/ruby_xml_parser.c
   packages-wip/libxml-ruby/trunk/ruby_xml_parser.h
   packages-wip/libxml-ruby/trunk/ruby_xml_parser_context.c
   packages-wip/libxml-ruby/trunk/ruby_xml_parser_context.h
   packages-wip/libxml-ruby/trunk/ruby_xml_sax_parser.c
   packages-wip/libxml-ruby/trunk/ruby_xml_sax_parser.h
   packages-wip/libxml-ruby/trunk/ruby_xml_schema.c
   packages-wip/libxml-ruby/trunk/ruby_xml_schema.h
   packages-wip/libxml-ruby/trunk/ruby_xml_tree.c
   packages-wip/libxml-ruby/trunk/ruby_xml_tree.h
   packages-wip/libxml-ruby/trunk/ruby_xml_xinclude.c
   packages-wip/libxml-ruby/trunk/ruby_xml_xinclude.h
   packages-wip/libxml-ruby/trunk/ruby_xml_xpath.c
   packages-wip/libxml-ruby/trunk/ruby_xml_xpath.h
   packages-wip/libxml-ruby/trunk/ruby_xml_xpath_context.c
   packages-wip/libxml-ruby/trunk/ruby_xml_xpath_context.h
   packages-wip/libxml-ruby/trunk/ruby_xml_xpointer.c
   packages-wip/libxml-ruby/trunk/ruby_xml_xpointer.h
   packages-wip/libxml-ruby/trunk/ruby_xml_xpointer_context.c
   packages-wip/libxml-ruby/trunk/ruby_xml_xpointer_context.h
   packages-wip/libxml-ruby/trunk/sax_parser_callbacks.inc
Log:
Load newtrunk into packages-wip/libxml-ruby/trunk.


Added: packages-wip/libxml-ruby/trunk/cbg.c
===================================================================
--- packages-wip/libxml-ruby/trunk/cbg.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/cbg.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,76 @@
+#include <string.h>
+#include <libxml/xmlIO.h>
+#include "ruby.h"
+
+/*
+int         xmlRegisterInputCallbacks       (xmlInputMatchCallback matchFunc,
+                                             xmlInputOpenCallback openFunc,
+                                             xmlInputReadCallback readFunc,
+                                             xmlInputCloseCallback closeFunc);
+
+
+int         (*xmlInputMatchCallback)        (char const *filename);
+void*       (*xmlInputOpenCallback)         (char const *filename);
+int         (*xmlInputReadCallback)         (void *context,
+                                             char *buffer,
+                                             int len);
+int         (*xmlInputCloseCallback)        (void *context);
+*/
+
+typedef struct deb_doc_context {
+    char *buffer;
+    char *bpos;
+    int remaining;
+} deb_doc_context;
+
+int deb_Match (char const *filename) {
+    fprintf( stderr, "deb_Match: %s\n", filename );
+    if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST "deb://", 6)) {
+        return(1);
+    }
+    return(0);
+}
+
+void* deb_Open (char const *filename) {
+    deb_doc_context *deb_doc;
+    VALUE res;
+
+    deb_doc = (deb_doc_context*)malloc( sizeof(deb_doc_context) );
+
+    res = rb_funcall( rb_funcall( rb_mKernel, rb_intern("const_get"), 1, rb_str_new2("DEBSystem") ),
+                      rb_intern("document_query"), 1, rb_str_new2(filename));
+    deb_doc->buffer = strdup( StringValuePtr(res) );
+    //deb_doc->buffer = strdup("<serepes>serepes</serepes>");
+
+    deb_doc->bpos = deb_doc->buffer;
+    deb_doc->remaining = strlen(deb_doc->buffer);
+    return deb_doc;
+}
+
+int deb_Read (void *context, char *buffer, int len) {
+    deb_doc_context *deb_doc;
+    int ret_len;
+    deb_doc = (deb_doc_context*)context;
+
+    if (len >= deb_doc->remaining) {
+        ret_len =  deb_doc->remaining;
+    } else {
+        ret_len = len;
+    }
+    deb_doc->remaining -= ret_len;
+    strncpy( buffer, deb_doc->bpos, ret_len );
+    deb_doc->bpos += ret_len;
+
+    return ret_len;
+}
+
+int deb_Close (void *context) {
+    free( ((deb_doc_context*)context)->buffer );
+    free( context );
+    return 1;
+}
+
+
+void deb_register_cbg() {
+    xmlRegisterInputCallbacks( deb_Match, deb_Open, deb_Read, deb_Close );
+}

Added: packages-wip/libxml-ruby/trunk/debian/changelog
===================================================================
--- packages-wip/libxml-ruby/trunk/debian/changelog	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/debian/changelog	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,41 @@
+libxml-ruby (0.3.8-1) unstable; urgency=low
+
+  * Package adopted. Closes: #335698.
+
+ -- Filipe Lautert <filipelautert at celepar.pr.gov.br>  Wed,  1 Nov 2006 15:35:12 -0300
+
+libxml-ruby (0.3.4-4) unstable; urgency=low
+
+  * QA upload.
+  * Add a libxml-ruby metapackage as recommended by Debian Ruby Policy.
+    Closes: #282759.
+  * Change section to interpreters.  Closes: #260944.
+  * debian/copyright: Update upstream URL.
+  * debian/dirs: $(sitedir) already handled by the Makefile; remove.
+  * debian/docs: README and TODO already handled by cdbs; remove.
+  * debian/watch: Add.
+  * Conforms to Standards version 3.6.2.
+
+ -- Matej Vela <vela at debian.org>  Sun, 13 Nov 2005 17:38:06 +0100
+
+libxml-ruby (0.3.4-3) unstable; urgency=low
+
+  * Orphaning package, setting maintainer to QA.
+
+ -- Andres Salomon <dilinger at voxel.net>  Tue, 25 Oct 2005 01:44:32 -0400
+
+libxml-ruby (0.3.4-2) unstable; urgency=low
+
+  * Fix FTBFS due to unnecessary libm/atan check; thanks to
+    Andreas Jochens (closes: #265475).
+  * Fix gcc-4.0 FTBFS due to lvalue casts; thanks to
+    Andreas Jochens (closes: #287452).
+
+ -- Andres Salomon <dilinger at voxel.net>  Wed, 29 Dec 2004 07:37:28 -0500
+
+libxml-ruby (0.3.4-1) unstable; urgency=low
+
+  * Initial release (closes: #228534).
+
+ -- Andres Salomon <dilinger at voxel.net>  Fri, 16 Jul 2004 22:12:41 -0400
+

Added: packages-wip/libxml-ruby/trunk/debian/compat
===================================================================
--- packages-wip/libxml-ruby/trunk/debian/compat	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/debian/compat	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1 @@
+4

Added: packages-wip/libxml-ruby/trunk/debian/control
===================================================================
--- packages-wip/libxml-ruby/trunk/debian/control	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/debian/control	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,23 @@
+Source: libxml-ruby
+Section: interpreters
+Priority: optional
+Maintainer: Filipe Lautert <filipelautert at celepar.pr.gov.br>
+Uploaders: Debian Ruby Extras Maintainers <pkg-ruby-extras-maintainers at lists.alioth.debian.org>, Antonio S. de A. Terceiro <asaterceiro at inf.ufrgs.br>, David Moreno Garza <damog at debian.org>, David Nusinow <dnusinow at debian.org>, Paul van Tilburg <paulvt at debian.org>, Esteban Manchado Velázquez <zoso at debian.org>, Arnaud Cornet <arnaud.cornet at gmail.com>, Lucas Nussbaum <lucas at lucas-nussbaum.net>, Thierry Reding <thierry at doppeltgemoppelt.de>, Marc Dequènes (Duck) <Duck at DuckCorp.org>, Ari Pollak <ari at debian.org>, Daigo Moriwaki <daigo at debian.org>, Vincent Fourmond <vincent.fourmond at 9online.fr>, Rudi Cilibrasi <cilibrar at cilibrar.com>, Patrick Ringl <patrick_ at freenet.de>
+Build-Depends: debhelper (>> 4.1.0), cdbs, ruby-pkg-tools (>= 0.8), ruby, ruby1.8-dev, libxml2-dev, libxslt1-dev, zlib1g-dev
+Standards-Version: 3.7.2
+
+Package: libxml-ruby
+Architecture: all
+Depends: libxml-ruby1.8
+Description: Ruby interface to libxml
+ libxml-ruby is a Ruby interface for processing XML.  It supports
+ XPath, XPointer, and other features.  Internally, it uses libxml
+ and libxslt.
+
+Package: libxml-ruby1.8
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: Ruby interface to libxml
+ libxml-ruby is a Ruby interface for processing XML.  It supports
+ XPath, XPointer, and other features.  Internally, it uses libxml
+ and libxslt.

Added: packages-wip/libxml-ruby/trunk/debian/control.in
===================================================================
--- packages-wip/libxml-ruby/trunk/debian/control.in	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/debian/control.in	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,23 @@
+Source: libxml-ruby
+Section: interpreters
+Priority: optional
+Maintainer: Filipe Lautert <filipelautert at celepar.pr.gov.br>
+Uploaders: @RUBY_EXTRAS_TEAM@
+Build-Depends: debhelper (>> 4.1.0), cdbs, ruby-pkg-tools (>= 0.8), ruby, ruby1.8-dev, libxml2-dev, libxslt1-dev, zlib1g-dev
+Standards-Version: 3.7.2
+
+Package: libxml-ruby
+Architecture: all
+Depends: libxml-ruby1.8
+Description: Ruby interface to libxml
+ libxml-ruby is a Ruby interface for processing XML.  It supports
+ XPath, XPointer, and other features.  Internally, it uses libxml
+ and libxslt.
+
+Package: libxml-ruby1.8
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: Ruby interface to libxml
+ libxml-ruby is a Ruby interface for processing XML.  It supports
+ XPath, XPointer, and other features.  Internally, it uses libxml
+ and libxslt.

Added: packages-wip/libxml-ruby/trunk/debian/copyright
===================================================================
--- packages-wip/libxml-ruby/trunk/debian/copyright	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/debian/copyright	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,22 @@
+# $Id: LICENSE,v 1.3 2006/02/28 09:57:52 roscopeco Exp $
+
+ Copyright (c) 2002-2006 Sean Chittenden <sean at chittenden.org> and contributors
+ Copyright (c) 2001 Wai-Sun "Squidster" Chia <waisun.chia at compaq.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in 
+the Software without restriction, including without limitation the rights to 
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

Added: packages-wip/libxml-ruby/trunk/debian/docs
===================================================================
--- packages-wip/libxml-ruby/trunk/debian/docs	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/debian/docs	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,3 @@
+README
+tests
+TODO

Added: packages-wip/libxml-ruby/trunk/debian/rules
===================================================================
--- packages-wip/libxml-ruby/trunk/debian/rules	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/debian/rules	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+#
+# CDBS file to build the Foo Ruby package.
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/ruby-pkg-tools/1/class/ruby-extconf-rb.mk
+include /usr/share/ruby-pkg-tools/1/rules/uploaders.mk
+
+DEB_COMPRESS_EXCLUDE := .xml


Property changes on: packages-wip/libxml-ruby/trunk/debian/rules
___________________________________________________________________
Name: svn:executable
   + *

Added: packages-wip/libxml-ruby/trunk/debian/watch
===================================================================
--- packages-wip/libxml-ruby/trunk/debian/watch	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/debian/watch	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,2 @@
+version=3
+http://rubyforge.org/frs/?group_id=494 .*/libxml-ruby-(.*)\.tar\.gz

Added: packages-wip/libxml-ruby/trunk/extconf.rb
===================================================================
--- packages-wip/libxml-ruby/trunk/extconf.rb	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/extconf.rb	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,95 @@
+#!/usr/bin/env ruby
+
+require 'mkmf'
+
+if defined?(CFLAGS)
+  if CFLAGS.index(CONFIG['CCDLFLAGS'])
+    $CFLAGS = CFLAGS
+  else
+    $CFLAGS = CFLAGS + ' ' + CONFIG['CCDLFLAGS']
+  end
+else
+  $CFLAGS = CONFIG['CFLAGS']
+end
+$LDFLAGS = CONFIG['LDFLAGS']
+$LIBPATH.push(Config::CONFIG['libdir'])
+
+def crash(str)
+  printf(" extconf failure: %s\n", str)
+  exit 1
+end
+
+dir_config('iconv')
+dir_config('xml2')
+dir_config('zlib')
+
+have_library('socket','socket')
+have_library('nsl','gethostbyname')
+
+unless have_library('m', 'atan')
+  # try again for gcc 4.0
+  saveflags = $CFLAGS
+  $CFLAGS += ' -fno-builtin'
+  unless have_library('m', 'atan')
+    crash('need libm')
+  end
+  $CFLAGS = saveflags
+end
+
+unless have_library('z', 'inflate')
+  crash('need zlib')
+else
+  $defs.push('-DHAVE_ZLIB_H')
+end
+
+unless have_library('iconv','iconv_open') or 
+       have_library('c','iconv_open') or
+       have_library('recode','iconv_open') or
+       have_library('iconv')
+  crash(<<EOL)
+need libiconv.
+
+	Install the libiconv or try passing one of the following options
+	to extconf.rb:
+
+	--with-iconv-dir=/path/to/iconv
+	--with-iconv-lib=/path/to/iconv/lib
+	--with-iconv-include=/path/to/iconv/include
+EOL
+end
+
+unless (have_library('xml2', 'xmlParseDoc') or
+        find_library('xml2', '/opt/lib', '/usr/local/lib', '/usr/lib')) and 
+       (have_header('libxml/xmlversion.h') or
+        find_header('libxml/xmlversion.h', 
+                    '/opt/include/libxml2', 
+                    '/usr/local/include/libxml2', 
+                    '/usr/include/libxml2'))
+  crash(<<EOL)
+need libxml2.
+
+        Install the library or try one of the following options to extconf.rb:
+
+        --with-xml2-dir=/path/to/libxml2
+        --with-xml2-lib=/path/to/libxml2/lib
+        --with-xml2-include=/path/to/libxml2/include
+EOL
+end
+
+unless have_library('xml2', 'xmlDocFormatDump')
+  crash('Your version of libxml2 is too old.  Please upgrade.')
+end
+
+unless have_func('docbCreateFileParserCtxt')
+  crash('Need docbCreateFileParserCtxt')
+end
+
+if try_compile('int main() { return 0; }','-Wall')
+  $CFLAGS << ' -Wall'
+end
+
+$CFLAGS << ' ' << $INCFLAGS
+$INSTALLFILES = [["../xml/libxml.rb", "$(RUBYLIBDIR)", "../xml"]]
+
+create_header()
+create_makefile('xml/libxml_so')

Added: packages-wip/libxml-ruby/trunk/libxml.c
===================================================================
--- packages-wip/libxml-ruby/trunk/libxml.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/libxml.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,86 @@
+/* $Id: libxml.c,v 1.2 2006/04/17 13:30:22 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+
+/* Ruby's util.h has ruby_strdup */
+#include "util.h"
+
+#ifdef xmlMalloc
+#undef xmlMalloc
+#endif
+#ifdef xmlRealloc
+#undef xmlRealloc
+#endif
+#ifdef xmlMemStrdup
+#undef xmlMemStrdup
+#endif
+#ifdef xmlMemFree
+#undef xmlMemFree
+#endif
+
+#ifdef RubyMemMalloc
+#undef RubyMemMalloc
+#endif
+#ifdef RubyMemRealloc
+#undef RubyMemRealloc
+#endif
+#ifdef RubyMemStrdup
+#undef RubyMemStrdup
+#endif
+#ifdef RubyMemFree
+#undef RubyMemFree
+#endif
+
+#define RubyMemFree     ruby_xfree
+#define RubyMemRealloc  ruby_xrealloc
+#define RubyMemMalloc   ruby_xmalloc
+#define RubyMemStrdup   ruby_strdup
+
+VALUE mXML;
+
+static xmlFreeFunc freeFunc = NULL;
+static xmlMallocFunc mallocFunc = NULL;
+static xmlReallocFunc reallocFunc = NULL;
+static xmlStrdupFunc strdupFunc = NULL;
+
+void
+Init_libxml_so(void) {
+  /* Some libxml memory goo that should be done before anything else */
+  xmlMemGet((xmlFreeFunc *) & freeFunc,
+            (xmlMallocFunc *) & mallocFunc,
+            (xmlReallocFunc *) & reallocFunc,
+            (xmlStrdupFunc *) & strdupFunc);
+
+  if (xmlMemSetup((xmlFreeFunc)RubyMemFree, (xmlMallocFunc)RubyMemMalloc,
+                  (xmlReallocFunc)RubyMemRealloc, (xmlStrdupFunc)RubyMemStrdup) != 0)
+    rb_fatal("could not install the memory handlers for libxml");
+  xmlInitParser();
+
+  mXML = rb_define_module("XML");
+
+  rb_define_const(mXML, "XML_NAMESPACE", rb_str_new2((const char*)XML_XML_NAMESPACE));
+
+  ruby_init_parser();
+  ruby_init_xml_parser_context();
+  ruby_init_xml_attr();
+  ruby_init_xml_attribute();
+  ruby_init_xml_document();
+  ruby_init_xml_node();
+  ruby_init_xml_node_set();
+  ruby_init_xml_ns();
+  ruby_init_xml_sax_parser();
+  ruby_init_xml_tree();
+  ruby_init_xml_xinclude();
+  ruby_init_xml_xpath();
+  ruby_init_xml_xpath_context();
+  ruby_init_xml_xpointer();
+  ruby_init_xml_xpointer_context();
+  ruby_init_input_callbacks(); /* MUFF */
+  ruby_init_xml_dtd();         /* MUFF */
+  ruby_init_xml_schema();      /* MUFF */
+
+  ruby_xml_parser_default_substitute_entities_set(cXMLParser, Qtrue);
+  ruby_xml_parser_default_load_external_dtd_set(cXMLParser, Qtrue);
+}

Added: packages-wip/libxml-ruby/trunk/libxml.h
===================================================================
--- packages-wip/libxml-ruby/trunk/libxml.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/libxml.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,82 @@
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_LIBXML_H__
+#define __RUBY_LIBXML_H__
+
+/* Don't nuke this block!  It is used for automatically updating the
+ * versions below. VERSION = string formatting, VERNUM = numbered
+ * version for inline testing: increment both or none at all. */
+#define RUBY_LIBXML_VERSION  "0.3.8"
+#define RUBY_LIBXML_VERNUM   38
+#define RUBY_LIBXML_VER_MAJ   0
+#define RUBY_LIBXML_VER_MIN   3
+#define RUBY_LIBXML_VER_MIC   8
+
+#include <ruby.h>
+#include <rubyio.h>
+#include <util.h>
+#include <libxml/parser.h>
+#include <libxml/parserInternals.h>
+#include <libxml/debugXML.h>
+#include <libxml/xmlversion.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/xpath.h>
+#include <libxml/valid.h>
+#include <libxml/catalog.h>
+#ifdef LIBXML_DEBUG_ENABLED
+#include <libxml/xpathInternals.h>
+#endif
+#ifdef LIBXML_XINCLUDE_ENABLED
+#include <libxml/xinclude.h>
+#endif
+#ifdef LIBXML_XPTR_ENABLED
+#include <libxml/xpointer.h>
+#endif
+
+#define RUBY_LIBXML_SRC_TYPE_NULL    0
+#define RUBY_LIBXML_SRC_TYPE_FILE    1
+#define RUBY_LIBXML_SRC_TYPE_STRING  2
+#define RUBY_LIBXML_SRC_TYPE_IO      3
+#define RUBY_LIBXML_SRC_TYPE_XPATH   4
+
+typedef struct rx_file_data {
+  VALUE filename; /* Filename/path to self */
+} rx_file_data;
+
+typedef struct rx_io_data {
+  VALUE io;
+} rx_io_data;
+
+typedef struct rx_string_data {
+  VALUE str;
+} rx_string_data;
+
+typedef struct rx_xpath_data {
+  VALUE ctxt;
+} rx_xpath_data;
+
+#include "ruby_xml_attr.h"
+#include "ruby_xml_attribute.h"
+#include "ruby_xml_document.h"
+#include "ruby_xml_node.h"
+#include "ruby_xml_node_set.h"
+#include "ruby_xml_ns.h"
+#include "ruby_xml_parser.h"
+#include "ruby_xml_parser_context.h"
+#include "ruby_xml_sax_parser.h"
+#include "ruby_xml_tree.h"
+#include "ruby_xml_xinclude.h"
+#include "ruby_xml_xpath.h"
+#include "ruby_xml_xpath_context.h"
+#include "ruby_xml_xpointer.h"
+#include "ruby_xml_xpointer_context.h"
+#include "ruby_xml_input_cbg.h"
+#include "ruby_xml_dtd.h"
+#include "ruby_xml_schema.h"
+
+extern VALUE mXML;
+
+void ruby_init_parser(void);
+void ruby_xml_parser_free(ruby_xml_parser *rxp);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/libxml.rb
===================================================================
--- packages-wip/libxml-ruby/trunk/libxml.rb	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/libxml.rb	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,107 @@
+# $Id: libxml.rb,v 1.1 2006/04/17 13:30:22 roscopeco Exp $ 
+# Please see the LICENSE file for copyright and distribution information 
+require 'xml/libxml_so'
+
+class XML::Node::Set
+  def empty? #:nodoc:
+  	self.length <= 0
+  end
+  
+  def first #:nodoc:
+  	self.each { |n| return n }
+  end
+end
+
+class XML::Document
+  include Enumerable
+
+  # maybe, maybe not...
+  def each(&blk) #:nodoc:
+    find('//*').each(&blk)
+  end
+end
+
+class XML::Node::Set 
+  # inefficient, but maybe can find a way to cache the
+  # ary and dump on change?
+  def [](i, count = nil) #:nodoc:
+    if count
+      to_a[i,count]
+    else
+      to_a[i]
+    end
+  end
+
+  def to_s #:nodoc:
+    to_a.to_s
+  end
+end
+
+module XML::SiblingEnum #:nodoc:all
+  private 
+  
+  # Iterates nodes and attributes
+  def siblings(node, &blk)
+    if n = node
+      loop do
+        blk.call(n)
+        break unless n = n.next
+      end
+    end 
+  end
+end
+
+class XML::Node
+  include XML::SiblingEnum
+  include Enumerable
+  include Comparable
+  
+  # maybe these don't belong on all nodes...
+  def each_child(&blk) #:nodoc:
+    siblings(child, &blk)   
+  end
+
+  def each_attr(&blk) #:nodoc:
+    siblings(properties, &blk)
+  end
+
+  # all siblings INCLUDING self
+  def each_sibling(&blk) #:nodoc:
+    siblings(self, &blk)
+  end
+  
+  # I guess this is what you'd expect?
+  alias :each :each_child
+
+  def to_a #:nodoc:
+    inject([]) { |ary,n| ary << n }
+  end
+  
+  def <=>(other) #:nodoc:
+    to_s <=> other.to_s
+  end  
+end
+
+class XML::Attr 
+  include XML::SiblingEnum
+  include Enumerable
+
+  def each_sibling(&blk) #:nodoc:
+    siblings(self,&blk)
+  end
+  
+  alias :each_attr :each_sibling
+  alias :each :each_sibling
+  
+  def to_h #:nodoc:
+    inject({}) do |h,a| h[a.name] = a.value end
+  end
+
+  def to_a #:nodoc:
+    inject([]) do |ary,a| ary << [a.name, a.value] end
+  end
+  
+  def to_s #:nodoc:
+    "#{name} = #{value}"
+  end
+end

Added: packages-wip/libxml-ruby/trunk/ruby_xml_attr.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_attr.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_attr.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,372 @@
+/* $Id: ruby_xml_attr.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_attr.h"
+
+VALUE cXMLAttr;
+
+void
+ruby_xml_attr_free(ruby_xml_attr *rxa) {
+  if (rxa->attr != NULL && !rxa->is_ptr) {
+    xmlUnlinkNode((xmlNodePtr)rxa->attr);
+    xmlFreeNode((xmlNodePtr)rxa->attr);
+    rxa->attr = NULL;
+  }
+
+  free(rxa);
+}
+
+
+/*
+ * call-seq:
+ *    attr.child => node
+ * 
+ * Obtain this attribute's child attribute(s).
+ */
+VALUE
+ruby_xml_attr_child_get(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->children == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attr->children));
+}
+
+
+/*
+ * call-seq:
+ *    attr.child? => (true|false)
+ * 
+ * Determine whether this attribute has child attributes.
+ */
+VALUE
+ruby_xml_attr_child_q(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->children == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    attr.doc => document
+ * 
+ * Obtain the XML::Document this attribute is associated with,
+ * if any.
+ */
+VALUE
+ruby_xml_attr_doc_get(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->doc == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_document_new(cXMLDocument, rxa->attr->doc));
+}
+
+
+/*
+ * call-seq:
+ *    attr.doc? => (true|false)
+ * 
+ * Determine whether this attribute is associated with an
+ * XML::Document.
+ */
+VALUE
+ruby_xml_attr_doc_q(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->doc == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    attr.last => node
+ * 
+ * Obtain the last attribute.
+ */
+VALUE
+ruby_xml_attr_last_get(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->last == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attr->last));
+}
+
+
+/*
+ * call-seq:
+ *    attr.last? => (true|false)
+ * 
+ * Determine whether this is the last attribute.
+ */
+VALUE
+ruby_xml_attr_last_q(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->last == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+static void
+ruby_xml_attr_mark(ruby_xml_attr *rxa) {
+  if (rxa == NULL) return;
+  if (!NIL_P(rxa->xd)) rb_gc_mark(rxa->xd);
+}
+
+
+/*
+ * call-seq:
+ *    attr.name => "name"
+ * 
+ * Obtain this attribute's name.
+ */
+VALUE
+ruby_xml_attr_name_get(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+
+  if (rxa->attr->name == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxa->attr->name));
+}
+
+
+VALUE
+ruby_xml_attr_new(VALUE class, VALUE xd, xmlAttrPtr attr) {
+  ruby_xml_attr *rxa;
+
+  rxa = ALLOC(ruby_xml_attr);
+  rxa->attr = attr;
+  rxa->xd = xd;
+  rxa->is_ptr = 0;
+  return(Data_Wrap_Struct(class, ruby_xml_attr_mark,
+			  ruby_xml_attr_free, rxa));
+}
+
+
+VALUE
+ruby_xml_attr_new2(VALUE class, VALUE xd, xmlAttrPtr attr) {
+  ruby_xml_attr *rxa;
+
+  rxa = ALLOC(ruby_xml_attr);
+  rxa->attr = xmlCopyProp(attr->parent, attr);
+  rxa->xd = xd;
+  rxa->is_ptr = 0;
+  return(Data_Wrap_Struct(class, ruby_xml_attr_mark,
+			  ruby_xml_attr_free, rxa));
+}
+
+
+/*
+ * call-seq:
+ *    attr.next => node
+ * 
+ * Obtain the next attribute.
+ */
+VALUE
+ruby_xml_attr_next_get(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->next == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_attr_new(cXMLAttr, rxa->xd, rxa->attr->next));
+}
+
+
+/*
+ * call-seq:
+ *    attr.next? => (true|false)
+ * 
+ * Determine whether there is a next attribute.
+ */
+VALUE
+ruby_xml_attr_next_q(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->next == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    attr.type_name => "attribute"
+ * 
+ * Obtain this attribute node's type name.
+ */
+VALUE
+ruby_xml_attr_node_type_name(VALUE self) {
+  /* I think libxml2's naming convention blows monkey ass */
+  return(rb_str_new2("attribute"));
+}
+
+
+/*
+ * call-seq:
+ *    attr.ns => namespace
+ * 
+ * Obtain this attribute's associated XML::NS, if any.
+ */
+VALUE
+ruby_xml_attr_ns_get(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->ns == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_ns_new2(cXMLNS, rxa->xd, rxa->attr->ns));
+}
+
+
+/*
+ * call-seq:
+ *    attr.ns? => (true|false)
+ * 
+ * Determine whether this attribute has an associated 
+ * namespace.
+ */
+VALUE
+ruby_xml_attr_ns_q(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->ns == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    attr.parent => node
+ * 
+ * Obtain this attribute node's parent.
+ */
+VALUE
+ruby_xml_attr_parent_get(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->parent == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attr->parent));
+}
+
+
+/*
+ * call-seq:
+ *    attr.parent? => (true|false)
+ * 
+ * Determine whether this attribute has a parent.
+ */
+VALUE
+ruby_xml_attr_parent_q(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->parent == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    attr.prev => node
+ * 
+ * Obtain the previous attribute.
+ */
+VALUE
+ruby_xml_attr_prev_get(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->prev == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_attr_new(cXMLAttr, rxa->xd, rxa->attr->prev));
+}
+
+
+/*
+ * call-seq:
+ *    attr.prev? => (true|false)
+ * 
+ * Determine whether there is a previous attribute.
+ */
+VALUE
+ruby_xml_attr_prev_q(VALUE self) {
+  ruby_xml_attr *rxa;
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (rxa->attr->prev == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    attr.value => "value"
+ * 
+ * Obtain the value of this attribute.
+ */
+VALUE
+ruby_xml_attr_value(VALUE self) {
+  ruby_xml_attr *rxa;
+  xmlChar *value;
+
+  Data_Get_Struct(self, ruby_xml_attr, rxa);
+  if (ruby_xml_attr_parent_q(self) == Qtrue) {
+    value = xmlGetProp(rxa->attr->parent, rxa->attr->name);
+    if (value != NULL)
+      return(rb_str_new2((const char*)value));
+  }
+  return(Qnil);
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_attr(void) {
+  cXMLAttr = rb_define_class_under(mXML, "Attr", rb_cObject);
+  rb_define_method(cXMLAttr, "child", ruby_xml_attr_child_get, 0);
+  rb_define_method(cXMLAttr, "child?", ruby_xml_attr_child_q, 0);
+  rb_define_method(cXMLAttr, "doc", ruby_xml_attr_doc_get, 0);
+  rb_define_method(cXMLAttr, "doc?", ruby_xml_attr_doc_q, 0);
+  rb_define_method(cXMLAttr, "last", ruby_xml_attr_last_get, 0);
+  rb_define_method(cXMLAttr, "last?", ruby_xml_attr_last_q, 0);
+  rb_define_method(cXMLAttr, "name", ruby_xml_attr_name_get, 0);
+  rb_define_method(cXMLAttr, "next", ruby_xml_attr_next_get, 0);
+  rb_define_method(cXMLAttr, "next?", ruby_xml_attr_next_q, 0);
+  rb_define_method(cXMLAttr, "node_type_name", ruby_xml_attr_node_type_name, 0);
+  rb_define_method(cXMLAttr, "ns", ruby_xml_attr_ns_get, 0);
+  rb_define_method(cXMLAttr, "ns?", ruby_xml_attr_ns_q, 0);
+  rb_define_method(cXMLAttr, "parent", ruby_xml_attr_parent_get, 0);
+  rb_define_method(cXMLAttr, "parent?", ruby_xml_attr_parent_q, 0);
+  rb_define_method(cXMLAttr, "prev", ruby_xml_attr_prev_get, 0);
+  rb_define_method(cXMLAttr, "prev?", ruby_xml_attr_prev_q, 0);
+  rb_define_method(cXMLAttr, "value", ruby_xml_attr_value, 0);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_attr.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_attr.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_attr.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,21 @@
+/* $Id: ruby_xml_attr.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_ATTR__
+#define __RUBY_XML_ATTR__
+
+extern VALUE cXMLAttr;
+
+typedef struct ruby_xml_attr {
+  xmlAttrPtr attr;
+  VALUE xd;
+  int is_ptr;
+} ruby_xml_attr;
+
+void ruby_xml_attr_free(ruby_xml_attr *rxn);
+void ruby_init_xml_attr(void);
+VALUE ruby_xml_attr_new(VALUE class, VALUE xd, xmlAttrPtr attr);
+VALUE ruby_xml_attr_new2(VALUE class, VALUE xd, xmlAttrPtr attr);
+VALUE ruby_xml_attr_name_get(VALUE self);
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_attribute.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_attribute.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_attribute.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,224 @@
+/* $Id: ruby_xml_attribute.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_attribute.h"
+
+VALUE cXMLAttribute;
+
+// TODO Wtf is this about? It's not referenced outside this file AFAIK...
+
+VALUE
+ruby_xml_attribute_child_get(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+  if (rxa->attribute->children == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->children));
+}
+
+
+VALUE
+ruby_xml_attribute_children_q(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+  if (rxa->attribute->children == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+VALUE
+ruby_xml_attribute_default_get(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+
+  if (rxa->attribute->defaultValue == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxa->attribute->defaultValue));
+}
+
+
+VALUE
+ruby_xml_attribute_element_get(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+
+  if (rxa->attribute->elem == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxa->attribute->elem));
+}
+
+
+void
+ruby_xml_attribute_free(ruby_xml_attribute *rxa) {
+ if (rxa->attribute != NULL && !rxa->is_ptr) {
+    xmlUnlinkNode((xmlNodePtr)rxa->attribute);
+    xmlFreeNode((xmlNodePtr)rxa->attribute);
+    rxa->attribute = NULL;
+  }
+
+  free(rxa);
+}
+
+
+VALUE
+ruby_xml_attribute_last_get(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+  if (rxa->attribute->last == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->last));
+}
+
+
+VALUE
+ruby_xml_attribute_last_q(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+  if (rxa->attribute->last == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+static void
+ruby_xml_attribute_mark(ruby_xml_attribute *rxa) {
+  if (rxa == NULL) return;
+  if (!NIL_P(rxa->xd)) rb_gc_mark(rxa->xd);
+}
+
+
+VALUE
+ruby_xml_attribute_name_get(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+
+  if (rxa->attribute->name == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxa->attribute->name));
+}
+
+
+VALUE
+ruby_xml_attribute_new(VALUE class, VALUE xd, xmlAttributePtr attribute) {
+  ruby_xml_attribute *rxa;
+
+  rxa = ALLOC(ruby_xml_attribute);
+  rxa->is_ptr = 0;
+  rxa->attribute = attribute;
+  if (NIL_P(xd))
+    rxa->xd = Qnil;
+  else
+    rxa->xd = xd;
+  return(Data_Wrap_Struct(class, ruby_xml_attribute_mark,
+			  ruby_xml_attribute_free, rxa));
+}
+
+
+VALUE
+ruby_xml_attribute_new2(VALUE class, VALUE xd, xmlAttributePtr attribute) {
+  ruby_xml_attribute *rxa;
+
+  rxa = ALLOC(ruby_xml_attribute);
+  rxa->is_ptr = 1;
+  rxa->attribute = attribute;
+  if (NIL_P(xd))
+    rxa->xd = Qnil;
+  else
+    rxa->xd = xd;
+  return(Data_Wrap_Struct(class, ruby_xml_attribute_mark,
+			  ruby_xml_attribute_free, rxa));
+}
+
+
+VALUE
+ruby_xml_attribute_next_get(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+  if (rxa->attribute->next == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->next));
+}
+
+
+VALUE
+ruby_xml_attribute_next_q(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+  if (rxa->attribute->next == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+VALUE
+ruby_xml_attribute_node_type_name(VALUE self) {
+  return(rb_str_new2("attribute"));
+}
+
+
+VALUE
+ruby_xml_attribute_prefix_get(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+
+  if (rxa->attribute->prefix == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxa->attribute->prefix));
+}
+
+
+VALUE
+ruby_xml_attribute_prev_get(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+  if (rxa->attribute->prev == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxa->xd, rxa->attribute->prev));
+}
+
+VALUE
+ruby_xml_attribute_prev_q(VALUE self) {
+  ruby_xml_attribute *rxa;
+  Data_Get_Struct(self, ruby_xml_attribute, rxa);
+  if (rxa->attribute->prev == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+// Rdoc maybe doesn't need to know 
+// #ifdef RDOC_NEVER_DEFINED
+//   mXML = rb_define_module("XML");
+// #endif
+
+void
+ruby_init_xml_attribute(void) {
+  cXMLAttribute = rb_define_class_under(mXML, "Attribute", rb_cObject);
+  rb_define_method(cXMLAttribute, "child", ruby_xml_attribute_child_get, 0);
+  rb_define_method(cXMLAttribute, "children?", ruby_xml_attribute_children_q, 0);
+  rb_define_method(cXMLAttribute, "default", ruby_xml_attribute_default_get, 0);
+  rb_define_method(cXMLAttribute, "element", ruby_xml_attribute_element_get, 0);
+  rb_define_method(cXMLAttribute, "last", ruby_xml_attribute_last_get, 0);
+  rb_define_method(cXMLAttribute, "last?", ruby_xml_attribute_last_q, 0);
+  rb_define_method(cXMLAttribute, "node_type_name", ruby_xml_attribute_node_type_name, 0);
+  rb_define_method(cXMLAttribute, "name", ruby_xml_attribute_name_get, 0);
+  rb_define_method(cXMLAttribute, "next", ruby_xml_attribute_next_get, 0);
+  rb_define_method(cXMLAttribute, "next?", ruby_xml_attribute_next_q, 0);
+  rb_define_method(cXMLAttribute, "prefix", ruby_xml_attribute_prefix_get, 0);
+  rb_define_method(cXMLAttribute, "prev", ruby_xml_attribute_prev_get, 0);
+  rb_define_method(cXMLAttribute, "prev?", ruby_xml_attribute_prev_q, 0);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_attribute.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_attribute.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_attribute.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,21 @@
+/* $Id: ruby_xml_attribute.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_ATTRIBUTE__
+#define __RUBY_XML_ATTRIBUTE__
+
+extern VALUE cXMLAttribute;
+
+typedef struct ruby_xml_attribute {
+  xmlAttributePtr attribute;
+  VALUE xd;
+  int is_ptr;
+} ruby_xml_attribute;
+
+void ruby_xml_attribute_free(ruby_xml_attribute *rxa);
+void ruby_init_xml_attribute(void);
+VALUE ruby_xml_attribute_new(VALUE class, VALUE xd, xmlAttributePtr attribute);
+VALUE ruby_xml_attribute_new2(VALUE class, VALUE xd, xmlAttributePtr attribute);
+VALUE ruby_xml_attribute_name_get(VALUE self);
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_document.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_document.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_document.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,1159 @@
+/* $Id: ruby_xml_document.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_document.h"
+
+VALUE cXMLDocument;
+
+/*
+ * call-seq:
+ *    document.compression => num
+ * 
+ * Obtain this document's compression mode identifier.
+ */
+VALUE
+ruby_xml_document_compression_get(VALUE self) {
+#ifdef HAVE_ZLIB_H
+  ruby_xml_document *rxd;
+  int compmode;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  compmode = xmlGetDocCompressMode(rxd->doc);
+  if (compmode == -1)
+    return(Qnil);
+  else
+    return(INT2NUM(compmode));
+#else
+  rb_warn("libxml not compiled with zlib support");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    document.compression = num
+ * 
+ * Set this document's compression mode.
+ */
+VALUE
+ruby_xml_document_compression_set(VALUE self, VALUE num) {
+#ifdef HAVE_ZLIB_H
+  ruby_xml_document *rxd;
+  int compmode;
+  Check_Type(num, T_FIXNUM);
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc == NULL) {
+    return(Qnil);
+  } else {
+    xmlSetDocCompressMode(rxd->doc, NUM2INT(num));
+
+    compmode = xmlGetDocCompressMode(rxd->doc);
+    if (compmode == -1)
+      return(Qnil);
+    else
+      return(INT2NUM(compmode));
+  }
+#else
+  rb_warn("libxml compiled without zlib support");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    document.compression? => (true|false)
+ * 
+ * Determine whether this document is compressed.
+ */
+VALUE
+ruby_xml_document_compression_q(VALUE self) {
+#ifdef HAVE_ZLIB_H
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->compression != -1)
+    return(Qtrue);
+  else
+    return(Qfalse);
+#else
+  rb_warn("libxml compiled without zlib support");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    document.child => node
+ * 
+ * Get this document's child node.
+ */
+VALUE
+ruby_xml_document_child_get(VALUE self) {
+  ruby_xml_document *rxd;
+  ruby_xml_node *rxn;
+  VALUE node;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->children == NULL)
+    return(Qnil);
+
+  node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->children);
+  Data_Get_Struct(node, ruby_xml_node, rxn);
+  rxn->xd = self;
+  return(node);
+}
+
+
+/*
+ * call-seq:
+ *    document.child? => (true|false)
+ * 
+ * Determine whether this document has a child node.
+ */
+VALUE
+ruby_xml_document_child_q(VALUE self) {
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->children == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    document.dump([stream]) => true
+ * 
+ * Dump this document's XML to the specified IO stream.
+ * If no stream is specified, stdout is used.
+ */
+VALUE
+ruby_xml_document_dump(int argc, VALUE *argv, VALUE self) {
+  OpenFile *fptr;
+  VALUE io;
+  FILE *out;
+  ruby_xml_document *rxd;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->doc == NULL)
+    return(Qnil);
+
+  switch (argc) {
+  case 0:
+    io = rb_stdout;
+    break;
+  case 1:
+    io = argv[0];
+    if (!rb_obj_is_kind_of(io, rb_cIO))
+      rb_raise(rb_eTypeError, "need an IO object");
+    break;
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
+  }
+
+  GetOpenFile(io, fptr);
+  rb_io_check_writable(fptr);
+  out = GetWriteFile(fptr);
+  xmlDocDump(out, rxd->doc);
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    document.debug_dump([stream]) => true
+ * 
+ * Debug version of dump.
+ */
+VALUE
+ruby_xml_document_debug_dump(int argc, VALUE *argv, VALUE self) {
+#ifdef LIBXML_DEBUG_ENABLED
+  OpenFile *fptr;
+  VALUE io;
+  FILE *out;
+  ruby_xml_document *rxd;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->doc == NULL)
+    return(Qnil);
+
+  switch (argc) {
+  case 0:
+    io = rb_stderr;
+    break;
+  case 1:
+    io = argv[0];
+    if (!rb_obj_is_kind_of(io, rb_cIO))
+      rb_raise(rb_eTypeError, "need an IO object");
+    break;
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
+  }
+
+  GetOpenFile(io, fptr);
+  rb_io_check_writable(fptr);
+  out = GetWriteFile(fptr);
+  xmlDebugDumpDocument(out, rxd->doc);
+  return(Qtrue);
+#else
+  rb_warn("libxml was compiled without debugging support.  Please recompile libxml and ruby-libxml");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    document.debug_dump_head([stream]) => true
+ * 
+ * Debug-dump this document's header to the specified IO stream.
+ * If no stream is specified, stdout is used.
+ */
+VALUE
+ruby_xml_document_debug_dump_head(int argc, VALUE *argv, VALUE self) {
+#ifdef LIBXML_DEBUG_ENABLED
+  OpenFile *fptr;
+  VALUE io;
+  FILE *out;
+  ruby_xml_document *rxd;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->doc == NULL)
+    return(Qnil);
+
+  switch (argc) {
+  case 0:
+    io = rb_stdout;
+    break;
+  case 1:
+    io = argv[0];
+    if (!rb_obj_is_kind_of(io, rb_cIO))
+      rb_raise(rb_eTypeError, "need an IO object");
+    break;
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
+  }
+
+  GetOpenFile(io, fptr);
+  rb_io_check_writable(fptr);
+  out = GetWriteFile(fptr);
+  xmlDebugDumpDocumentHead(out, rxd->doc);
+  return(Qtrue);
+#else
+  rb_warn("libxml was compiled without debugging support.  Please recompile libxml and ruby-libxml");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    document.format_dump([stream], [spacing]) => true
+ * 
+ * Dump this document's formatted XML to the specified IO stream.
+ * If no stream is specified, stdout is used. If spacing is 
+ * specified, it must be a boolean that determines whether 
+ * spacing is used.
+ */
+VALUE
+ruby_xml_document_format_dump(int argc, VALUE *argv, VALUE self) {
+  OpenFile *fptr;
+  VALUE bool, io;
+  FILE *out;
+  ruby_xml_document *rxd;
+  int size, spacing;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->doc == NULL)
+    return(Qnil);
+
+  switch (argc) {
+  case 0:
+    io = rb_stdout;
+    spacing = 1;
+    break;
+  case 1:
+    io = argv[0];
+    if (!rb_obj_is_kind_of(io, rb_cIO))
+      rb_raise(rb_eTypeError, "need an IO object");
+    spacing = 1;
+    break;
+  case 2:
+    io = argv[0];
+    if (!rb_obj_is_kind_of(io, rb_cIO))
+      rb_raise(rb_eTypeError, "need an IO object");
+    bool = argv[1];
+    if (TYPE(bool) == T_TRUE)
+      spacing = 1;
+    else if (TYPE(bool) == T_FALSE)
+      spacing = 0;
+    else
+      rb_raise(rb_eTypeError, "incorect argument type, second argument must be bool");
+
+    break;
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
+  }
+
+  GetOpenFile(io, fptr);
+  rb_io_check_writable(fptr);
+  out = GetWriteFile(fptr);
+  size = xmlDocFormatDump(out, rxd->doc, spacing);
+  return(INT2NUM(size));
+}
+
+
+/*
+ * call-seq:
+ *    document.debug_format_dump([stream]) => true
+ * 
+ * *Deprecated* in favour of format_dump.
+ */
+VALUE
+ruby_xml_document_debug_format_dump(int argc, VALUE *argv, VALUE self) {
+  rb_warn("debug_format_dump has been deprecaited, use format_dump instead");
+  return(ruby_xml_document_format_dump(argc, argv, self));
+}
+
+
+/*
+ * call-seq:
+ *    document.encoding => "encoding"
+ * 
+ * Obtain the encoding specified by this document.
+ */
+VALUE
+ruby_xml_document_encoding_get(VALUE self) {
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->doc->encoding == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxd->doc->encoding));
+}
+
+
+/*
+ * call-seq:
+ *    document.encoding = "encoding"
+ * 
+ * Set the encoding for this document.
+ */
+VALUE
+ruby_xml_document_encoding_set(VALUE self, VALUE encoding) {
+  ruby_xml_document *rxd;
+
+  Check_Type(encoding, T_STRING);
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  rxd->doc->encoding = (xmlChar*)ruby_strdup(StringValuePtr(encoding));
+  return(ruby_xml_document_encoding_get(self));
+}
+
+
+/*
+ * call-seq:
+ *    document.filename => "filename"
+ * 
+ * Obtain the filename this document was read from.
+ */
+VALUE
+ruby_xml_document_filename_get(VALUE self) {
+  ruby_xml_document *rxd;
+  rx_file_data *data;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->data == NULL)
+    return(Qnil);
+
+  switch (rxd->data_type) {
+  case RUBY_LIBXML_SRC_TYPE_NULL:
+    return(Qnil);
+  case RUBY_LIBXML_SRC_TYPE_FILE:
+    data = (rx_file_data *)rxd->data;
+    return(data->filename);
+  default:
+    rb_fatal("Unknown document type in libxml");
+  }
+
+  return(Qnil);
+}
+
+
+/*
+ * call-seq:
+ *    document.find(xpath_expr, [namespace]) => nodeset
+ * 
+ * Find nodes matching the specified xpath expression, optionally
+ * using the specified namespace. Returns an XML::Node::Set.
+ */
+VALUE
+ruby_xml_document_find(int argc, VALUE *argv, VALUE self) {
+  int i, vargc;
+  VALUE *vargv;
+
+  if (argc > 2 || argc < 1)
+    rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
+
+  vargc = argc + 1;
+  vargv = ALLOC_N(VALUE, vargc + 1);
+  vargv[0] = ruby_xml_document_root_get(self);
+  for (i = 0; i<argc; i++)
+    vargv[i + 1] = argv[i];
+
+  return(ruby_xml_xpath_find2(vargc, vargv));
+}
+
+
+void
+ruby_xml_document_free(ruby_xml_document *rxd) {
+  void *data;
+
+  if (rxd->doc != NULL && !rxd->is_ptr) {
+    xmlFreeDoc(rxd->doc);
+    ruby_xml_parser_count--;
+    rxd->doc = NULL;
+  }
+
+  if (ruby_xml_parser_count == 0)
+    xmlCleanupParser();
+
+  switch(rxd->data_type) {
+  case RUBY_LIBXML_SRC_TYPE_NULL:
+    break;
+  case RUBY_LIBXML_SRC_TYPE_FILE:
+    data = (void*)(rx_file_data *)rxd->data;
+    free((rx_file_data *)data);
+    break;
+  case RUBY_LIBXML_SRC_TYPE_STRING:
+    data = (void*)(rx_string_data *)rxd->data;
+    free((rx_string_data *)data);
+    break;
+  case RUBY_LIBXML_SRC_TYPE_IO:
+    data = (void*)(rx_io_data *)rxd->data;
+    free((rx_io_data *)data);
+    break;
+  default:
+    rb_fatal("Unknown data type, %d", rxd->data_type);
+  }
+
+  free(rxd);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Document.new(xml_version = 1.0) => document
+ * 
+ * Create a new XML::Document, optionally specifying the
+ * XML version.
+ */
+VALUE
+ruby_xml_document_initialize(int argc, VALUE *argv, VALUE class) {
+  VALUE docobj, xmlver;
+
+  switch (argc) {
+  case 0:
+    xmlver = rb_str_new2("1.0");
+    break;
+  case 1:
+    rb_scan_args(argc, argv, "01", &xmlver);
+    break;
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (need 0 or 1)");
+  }
+
+  docobj = ruby_xml_document_new2(cXMLDocument, xmlver);
+  return(docobj);
+}
+
+
+/*
+ * call-seq:
+ *    document.last => node
+ * 
+ * Obtain the last node.
+ */
+VALUE
+ruby_xml_document_last_get(VALUE self) {
+  ruby_xml_document *rxd;
+  ruby_xml_node *rxn;
+  VALUE node;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->last == NULL)
+    return(Qnil);
+
+  node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->last);
+  Data_Get_Struct(node, ruby_xml_node, rxn);
+  rxn->xd = self;
+  return(node);
+}
+
+
+/*
+ * call-seq:
+ *    document.last? => (true|false)
+ * 
+ * Determine whether there is a last node.
+ */
+VALUE
+ruby_xml_document_last_q(VALUE self) {
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->last == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+static void
+ruby_xml_document_mark(ruby_xml_document *rxd) {
+  if (rxd == NULL) return;
+  if (!NIL_P(rxd->xmlver)) rb_gc_mark(rxd->xmlver);
+}
+
+
+VALUE
+ruby_xml_document_new(VALUE class, xmlDocPtr doc) {
+  ruby_xml_document *rxd;
+
+  rxd = ALLOC(ruby_xml_document);
+  ruby_xml_parser_count++;
+
+  rxd->data = NULL;
+  rxd->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
+  rxd->doc = doc;
+  rxd->is_ptr = 0;
+  rxd->xmlver = Qnil;
+
+  return(Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark,
+			  ruby_xml_document_free, rxd));
+}
+
+
+VALUE
+ruby_xml_document_new2(VALUE class, VALUE xmlver) {
+  ruby_xml_document *rxd;
+
+  Check_Type(xmlver, T_STRING);
+  rxd = ALLOC(ruby_xml_document);
+  ruby_xml_parser_count++;
+
+  rxd->data = NULL;
+  rxd->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
+  rxd->doc = xmlNewDoc((xmlChar*)StringValuePtr(xmlver));
+  rxd->is_ptr = 0;
+  rxd->xmlver = xmlver;
+
+  if (rxd->doc == NULL)
+    rb_fatal("bad");
+
+  return(Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark,
+			  ruby_xml_document_free, rxd));
+}
+
+
+VALUE
+ruby_xml_document_new3(VALUE class) {
+  return(ruby_xml_document_new2(class, rb_str_new2("1.0")));
+}
+
+
+VALUE
+ruby_xml_document_new4(VALUE class, xmlDocPtr doc) {
+  ruby_xml_document *rxd;
+
+  rxd = ALLOC(ruby_xml_document);
+
+  rxd->data = NULL;
+  rxd->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
+  rxd->doc = doc;
+  rxd->is_ptr = 1;
+  rxd->xmlver = Qnil;
+
+  return(Data_Wrap_Struct(cXMLDocument, ruby_xml_document_mark,
+			  ruby_xml_document_free, rxd));
+}
+
+
+/*
+ * call-seq:
+ *    XML::Document.file(filename) => document
+ * 
+ * Create a new XML::Document by parsing the specified
+ * file.
+ */
+VALUE
+ruby_xml_document_new_file(VALUE class, VALUE filename) {
+  VALUE parser;
+
+  parser = ruby_xml_parser_new(cXMLParser);
+  ruby_xml_parser_filename_set(parser, filename);
+  return(ruby_xml_parser_parse(parser));
+}
+
+
+/*
+ * call-seq:
+ *    document.next => node
+ * 
+ * Obtain the next node.
+ */
+VALUE
+ruby_xml_document_next_get(VALUE self) {
+  ruby_xml_document *rxd;
+  ruby_xml_node *rxn;
+  VALUE node;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->next == NULL)
+    return(Qnil);
+
+  node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->next);
+  Data_Get_Struct(node, ruby_xml_node, rxn);
+  rxn->xd = self;
+  return(node);
+}
+
+
+/*
+ * call-seq:
+ *    document.next? => (true|false)
+ * 
+ * Determine whether there is a next node.
+ */
+VALUE
+ruby_xml_document_next_q(VALUE self) {
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->next == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    document.parent => node
+ * 
+ * Obtain the parent node.
+ */
+VALUE
+ruby_xml_document_parent_get(VALUE self) {
+  ruby_xml_document *rxd;
+  ruby_xml_node *rxn;
+  VALUE node;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->parent == NULL)
+    return(Qnil);
+
+  node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->parent);
+  Data_Get_Struct(node, ruby_xml_node, rxn);
+  rxn->xd = self;
+  return(node);
+}
+
+
+/*
+ * call-seq:
+ *    document.parent? => (true|false)
+ * 
+ * Determine whether there is a parent node.
+ */
+VALUE
+ruby_xml_document_parent_q(VALUE self) {
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->parent == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    document.prev => node
+ * 
+ * Obtain the previous node.
+ */
+VALUE
+ruby_xml_document_prev_get(VALUE self) {
+  ruby_xml_document *rxd;
+  ruby_xml_node *rxn;
+  VALUE node;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->prev == NULL)
+    return(Qnil);
+
+  node = ruby_xml_node_new2(cXMLNode, self, rxd->doc->prev);
+  Data_Get_Struct(node, ruby_xml_node, rxn);
+  rxn->xd = self;
+  return(node);
+}
+
+
+/*
+ * call-seq:
+ *    document.prev? => (true|false)
+ * 
+ * Determine whether there is a previous node.
+ */
+VALUE
+ruby_xml_document_prev_q(VALUE self) {
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+
+  if (rxd->doc->prev == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    document["key"] => "value"
+ * 
+ * Obtain the named property.
+ */
+VALUE
+ruby_xml_document_property_get(VALUE self, VALUE key) {
+  return(ruby_xml_node_property_get(ruby_xml_document_root_get(self), key));
+}
+
+
+/*
+ * call-seq:
+ *    document["key"] = "value"
+ * 
+ * Set the named property.
+ */
+VALUE
+ruby_xml_document_property_set(VALUE self, VALUE key, VALUE val) {
+  return(ruby_xml_node_property_set(ruby_xml_document_root_get(self), key, val));
+}
+
+
+/*
+ * call-seq:
+ *    document.root => node
+ * 
+ * Obtain the root node.
+ */
+VALUE
+ruby_xml_document_root_get(VALUE self) {
+  ruby_xml_document *rxd;
+  ruby_xml_node *rxn;
+  VALUE node;
+  xmlNodePtr root;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  root = xmlDocGetRootElement(rxd->doc);
+
+  if (root == NULL)
+    return(Qnil);
+
+  node = ruby_xml_node_new2(cXMLNode, self, root);
+  Data_Get_Struct(node, ruby_xml_node, rxn);
+  rxn->xd = self;
+  return(node);
+}
+
+
+/*
+ * call-seq:
+ *    document.root = node
+ * 
+ * Set the root node.
+ */
+VALUE
+ruby_xml_document_root_set(VALUE self, VALUE node) {
+  ruby_xml_document *rxd;
+  ruby_xml_node *rxn;
+  VALUE retnode;
+  xmlNodePtr root;
+
+  if (rb_obj_is_kind_of(node, cXMLNode) == Qfalse)
+    rb_raise(rb_eTypeError, "must pass an XML::Node type object");
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  Data_Get_Struct(node, ruby_xml_node, rxn);
+  ruby_xml_node_set_ptr(node, 1);
+  root = xmlDocSetRootElement(rxd->doc, rxn->node);
+  if (root == NULL)
+    return(Qnil);
+
+  retnode = ruby_xml_node_new2(cXMLNode, self, root);
+  return(retnode);
+}
+
+
+/*
+ * call-seq:
+ *    document.save(format = false)
+ * 
+ * Save this document to the file given by filename, 
+ * optionally formatting the output.
+ */
+VALUE
+ruby_xml_document_save(int argc, VALUE *argv, VALUE self) {
+  ruby_xml_document *rxd;
+  const char *filename;
+  int format, len;
+
+  format = 0;
+  switch (argc) {
+  case 1:
+    break;
+  case 2:
+    if (TYPE(argv[1]) == T_TRUE)
+      format = 1;
+    else if (TYPE(argv[1]) == T_FALSE)
+      format = 0;
+    else
+      rb_raise(rb_eTypeError, "wrong type of argument, must be bool");
+    break;
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
+  }
+
+  Check_Type(argv[0], T_STRING);
+  filename = StringValuePtr(argv[0]);
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  len = xmlSaveFormatFileEnc(filename, rxd->doc, (const char*)rxd->doc->encoding, format);
+  if (len == -1)
+    rb_fatal("Unable to write out file");
+  else
+    return(INT2NUM(len));
+}
+
+
+/*
+ * call-seq:
+ *    document.standalone? => (true|false)
+ * 
+ * Determine whether this is a standalone document.
+ */
+VALUE
+ruby_xml_document_standalone_q(VALUE self) {
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->doc->standalone)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    document.to_s => "xml"
+ * 
+ * Coerce this document to a string representation
+ * of it's XML.
+ */
+VALUE
+ruby_xml_document_to_s(int argc, VALUE *argv, VALUE self) {
+  ruby_xml_document *rxd;
+  xmlChar *result;
+  int format, len;
+
+  switch (argc) {
+  case 0:
+    format = 1;
+    break;
+  case 1:
+    if (TYPE(argv[0]) == T_TRUE)
+      format = 1;
+    else if (TYPE(argv[0]) == T_FALSE)
+      format = 0;
+    else
+      rb_raise(rb_eTypeError, "wrong type of argument, must be bool");
+    break;
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (0 or 1)");
+  }
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->doc == NULL) {
+    return(Qnil);
+  } else if (rxd->doc->encoding != NULL) {
+    if (format) {
+      xmlDocDumpFormatMemoryEnc(rxd->doc, &result, &len,
+				(const char*)rxd->doc->encoding, format);
+    } else {
+      xmlDocDumpMemoryEnc(rxd->doc, &result, &len,
+			  (const char*)rxd->doc->encoding);
+    }
+  } else {
+    if (format)
+      xmlDocDumpFormatMemory(rxd->doc, &result, &len, format);
+    else
+      xmlDocDumpMemory(rxd->doc, &result, &len);
+  }
+
+  return(rb_str_new2((const char*)result)); 
+}
+
+
+/*
+ * call-seq:
+ *    document.url => "url"
+ * 
+ * Obtain this document's source URL, if any.
+ */
+VALUE
+ruby_xml_document_url_get(VALUE self) {
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->doc->URL == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxd->doc->URL));
+}
+
+
+/*
+ * call-seq:
+ *    document.version => "version"
+ * 
+ * Obtain the XML version specified by this document.
+ */
+VALUE
+ruby_xml_document_version_get(VALUE self) {
+  ruby_xml_document *rxd;
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  if (rxd->doc->version == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxd->doc->version));
+}
+
+
+/*
+ * call-seq:
+ *    document.xinclude => num
+ * 
+ * Process xinclude directives in this document. 
+ */
+VALUE
+ruby_xml_document_xinclude(VALUE self) {
+#ifdef LIBXML_XINCLUDE_ENABLED
+  ruby_xml_document *rxd;
+  int ret;
+
+  Data_Get_Struct(self, ruby_xml_document, rxd);
+  ret = xmlXIncludeProcess(rxd->doc);
+  if (ret >= 0)
+    return(INT2NUM(ret));
+  else
+    rb_raise(eXMLXIncludeError, "error processing xinclude directives in document");
+#else
+  rb_warn("libxml was compiled without XInclude support.  Please recompile libxml and ruby-libxml");
+  return(Qfalse);
+#endif
+}
+
+void
+LibXML_validity_error(void * ctxt, const char * msg, va_list ap)
+{
+  if (rb_block_given_p()) {
+    char buff[1024];
+    snprintf(buff, 1024, msg, ap);
+    rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qtrue));
+  } else {
+    fprintf(stderr, "error -- found validity error: ");
+    fprintf(stderr, msg, ap);
+  }
+}
+
+void
+LibXML_validity_warning(void * ctxt, const char * msg, va_list ap)
+{
+  if (rb_block_given_p()) {
+    char buff[1024];
+    snprintf(buff, 1024, msg, ap);
+    rb_yield(rb_ary_new3(2, rb_str_new2(buff), Qfalse));
+  } else {
+    fprintf(stderr, "warning -- found validity error: ");
+    fprintf(stderr, msg, ap);
+  }
+}
+
+/*
+ * call-seq:
+ *    document.validate(schema) => (true|false)
+ * 
+ * Validate this document against the specified XML::Schema.
+ */
+VALUE
+ruby_xml_document_validate_schema(VALUE self, VALUE schema) {
+  xmlSchemaValidCtxtPtr vptr;
+  ruby_xml_document     *c_doc;
+  ruby_xml_schema       *c_schema;
+  int is_invalid;
+
+  Data_Get_Struct(self,   ruby_xml_document, c_doc);
+  Data_Get_Struct(schema, ruby_xml_schema,   c_schema);
+
+  vptr = xmlSchemaNewValidCtxt(c_schema->schema);
+
+  xmlSchemaSetValidErrors(vptr, (xmlSchemaValidityErrorFunc)LibXML_validity_error,
+                                (xmlSchemaValidityWarningFunc)LibXML_validity_warning, NULL);
+  
+  is_invalid = xmlSchemaValidateDoc(vptr, c_doc->doc);
+  xmlSchemaFreeValidCtxt(vptr);
+  if (is_invalid) {
+	return Qfalse;
+  } else {
+	return Qtrue;
+  }
+}
+
+
+/*
+ * call-seq:
+ *    document.validate(schema) => (true|false)
+ * 
+ * Validate this document against the specified XML::DTD.
+ */
+VALUE
+ruby_xml_document_validate_dtd(VALUE self, VALUE dtd) {
+  xmlValidCtxt cvp;
+  ruby_xml_document *c_doc;
+  ruby_xml_dtd *c_dtd;
+
+  Data_Get_Struct(self, ruby_xml_document, c_doc);
+  Data_Get_Struct(dtd,  ruby_xml_dtd,      c_dtd);
+
+  cvp.userData = NULL;
+  cvp.error = (xmlValidityErrorFunc)LibXML_validity_error;
+  cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
+
+  cvp.nodeNr = 0;
+  cvp.nodeTab = NULL;
+  cvp.vstateNr = 0;
+  cvp.vstateTab = NULL;
+
+  if ( xmlValidateDtd(&cvp, c_doc->doc, c_dtd->dtd) )
+    return(Qtrue);
+  else
+    return(Qfalse);
+
+//    int	xmlValidateDtd(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd)
+/*
+int
+validate(self, ...)
+        xmlDocPtr self
+    PREINIT:
+        xmlValidCtxt cvp;
+        xmlDtdPtr dtd;
+        SV * dtd_sv;
+        STRLEN n_a, len;
+    CODE:
+        LibXML_init_error();
+        cvp.userData = (void*)PerlIO_stderr();
+        cvp.error = (xmlValidityErrorFunc)LibXML_validity_error;
+        cvp.warning = (xmlValidityWarningFunc)LibXML_validity_warning;
+        // we need to initialize the node stack, because perl might 
+        // already messed it up.
+        //
+        cvp.nodeNr = 0;
+        cvp.nodeTab = NULL;
+        cvp.vstateNr = 0;
+        cvp.vstateTab = NULL;
+
+        if (items > 1) {
+            dtd_sv = ST(1);
+            if ( sv_isobject(dtd_sv) && (SvTYPE(SvRV(dtd_sv)) == SVt_PVMG) ) {
+                dtd = (xmlDtdPtr)PmmSvNode(dtd_sv);
+            }
+            else {
+                croak("is_valid: argument must be a DTD object");
+            }
+            RETVAL = xmlValidateDtd(&cvp, self , dtd);
+        }
+        else {
+            RETVAL = xmlValidateDocument(&cvp, self);
+        }
+        sv_2mortal(LibXML_error);
+
+        if (RETVAL == 0) {
+            LibXML_croak_error();
+        }
+    OUTPUT:
+        RETVAL
+*/
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_document(void) {
+  cXMLDocument = rb_define_class_under(mXML, "Document", rb_cObject);
+  rb_define_singleton_method(cXMLDocument, "file", ruby_xml_document_new_file, 1);
+  rb_define_singleton_method(cXMLDocument, "new", ruby_xml_document_initialize, -1);
+
+  //rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
+  //eDTDValidityWarning = rb_define_class_under(cXMLNode, "ValidityWarning", rb_eException);
+  //eDTDValidityError   = rb_define_class_under(cXMLNode, "ValidityWarning", rb_eException);
+  rb_define_method(cXMLDocument, "[]", ruby_xml_document_property_get, 1);
+  rb_define_method(cXMLDocument, "[]=", ruby_xml_document_property_set, 2);
+  rb_define_method(cXMLDocument, "child", ruby_xml_document_child_get, 0);
+  rb_define_method(cXMLDocument, "child?", ruby_xml_document_child_q, 0);
+  rb_define_method(cXMLDocument, "compression", ruby_xml_document_compression_get, 0);
+  rb_define_method(cXMLDocument, "compression=", ruby_xml_document_compression_set, 1);
+  rb_define_method(cXMLDocument, "compression?", ruby_xml_document_compression_q, 0);
+  rb_define_method(cXMLDocument, "dump", ruby_xml_document_dump, -1);
+  rb_define_method(cXMLDocument, "debug_dump", ruby_xml_document_debug_dump, -1);
+  rb_define_method(cXMLDocument, "debug_dump_head", ruby_xml_document_debug_dump_head, -1);
+  rb_define_method(cXMLDocument, "debug_format_dump", ruby_xml_document_debug_format_dump, -1);
+  rb_define_method(cXMLDocument, "encoding", ruby_xml_document_encoding_get, 0);
+  rb_define_method(cXMLDocument, "encoding=", ruby_xml_document_encoding_set, 1);
+  rb_define_method(cXMLDocument, "filename", ruby_xml_document_filename_get, 0);
+  rb_define_method(cXMLDocument, "find", ruby_xml_document_find, -1);
+  rb_define_method(cXMLDocument, "format_dump", ruby_xml_document_format_dump, -1);
+  rb_define_method(cXMLDocument, "last", ruby_xml_document_last_get, 0);
+  rb_define_method(cXMLDocument, "last?", ruby_xml_document_last_q, 0);
+  rb_define_method(cXMLDocument, "next", ruby_xml_document_next_get, 0);
+  rb_define_method(cXMLDocument, "next?", ruby_xml_document_next_q, 0);
+  rb_define_method(cXMLDocument, "parent", ruby_xml_document_parent_get, 0);
+  rb_define_method(cXMLDocument, "parent?", ruby_xml_document_parent_q, 0);
+  rb_define_method(cXMLDocument, "prev", ruby_xml_document_prev_get, 0);
+  rb_define_method(cXMLDocument, "prev?", ruby_xml_document_prev_q, 0);
+  rb_define_method(cXMLDocument, "root", ruby_xml_document_root_get, 0);
+  rb_define_method(cXMLDocument, "root=", ruby_xml_document_root_set, 1);
+  rb_define_method(cXMLDocument, "save", ruby_xml_document_save, -1);
+  rb_define_method(cXMLDocument, "standalone?", ruby_xml_document_standalone_q, 0);
+  rb_define_method(cXMLDocument, "to_s", ruby_xml_document_to_s, -1);
+  rb_define_method(cXMLDocument, "url", ruby_xml_document_url_get, 0);
+  rb_define_method(cXMLDocument, "version", ruby_xml_document_version_get, 0);
+  rb_define_method(cXMLDocument, "xinclude", ruby_xml_document_xinclude, 0);
+  rb_define_method(cXMLDocument, "validate", ruby_xml_document_validate_dtd, 1);
+  rb_define_method(cXMLDocument, "validate_schema", ruby_xml_document_validate_schema, 1);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_document.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_document.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_document.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,27 @@
+/* $Id: ruby_xml_document.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_DOCUMENT__
+#define __RUBY_XML_DOCUMENT__
+
+extern VALUE cXMLDocument;
+
+typedef struct rxp_document {
+  xmlDocPtr doc;   /* Tree/DOM interface */
+  int data_type;   /* The data type referenced by *data */
+  void *data;      /* Pointer to an external structure of options */
+  int is_ptr;      /* Determines if this object owns its data or points to it someplace else */
+  VALUE xmlver;    /* T_STRING with the xml version */
+} ruby_xml_document;
+
+VALUE ruby_xml_document_filename_get(VALUE self);
+void  ruby_xml_document_free(ruby_xml_document *rxd);
+VALUE ruby_xml_document_new(VALUE class, xmlDocPtr doc);
+VALUE ruby_xml_document_new2(VALUE class, VALUE xmlver);
+VALUE ruby_xml_document_new3(VALUE class);
+VALUE ruby_xml_document_new4(VALUE class, xmlDocPtr doc);
+VALUE ruby_xml_document_root_get(VALUE self);
+void  ruby_init_xml_document(void);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_dtd.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_dtd.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_dtd.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,168 @@
+#include "libxml.h"
+#include "ruby_xml_dtd.h"
+
+VALUE cXMLDtd;
+
+void
+ruby_xml_dtd_free(ruby_xml_dtd *rxdtd) {
+  if (rxdtd->dtd != NULL) {
+    xmlFreeDtd(rxdtd->dtd);
+    rxdtd->dtd = NULL;
+  }
+
+  free(rxdtd);
+}
+
+static void
+ruby_xml_dtd_mark(ruby_xml_dtd *rxdtd) {
+  return;
+  //if (rxdtd == NULL) return;
+  //if (!NIL_P(rxd->xmlver)) rb_gc_mark(rxd->xmlver);
+}
+
+/*
+ * call-seq:
+ *    XML::Dtd.new("public system") => dtd
+ *    XML::Dtd.new("public", "system") => dtd
+ * 
+ * Create a new Dtd from the specified public and system
+ * identifiers.
+ */
+VALUE
+ruby_xml_dtd_initialize(int argc, VALUE *argv, VALUE class) {
+  ruby_xml_dtd *rxdtd;
+  VALUE external, system, dtd_string;
+  xmlParserInputBufferPtr buffer;
+  xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
+  xmlChar *new_string;
+
+  // 1 argument -- string               --> parsujeme jako dtd
+  // 2 argumenty -- public, system      --> bude se hledat
+  switch (argc) {
+  case 2:
+    rb_scan_args(argc, argv, "20", &external, &system);
+
+    Check_Type(external, T_STRING);
+    Check_Type(system,   T_STRING);
+    rxdtd = ALLOC(ruby_xml_dtd);
+    rxdtd->dtd = xmlParseDTD( (xmlChar*)StringValuePtr(external),
+                              (xmlChar*)StringValuePtr(system) );
+    if (rxdtd->dtd == NULL) {
+      free(rxdtd);
+      return(Qfalse);
+    }
+
+    xmlSetTreeDoc( (xmlNodePtr)rxdtd->dtd, NULL );
+    return( Data_Wrap_Struct(cXMLDtd, ruby_xml_dtd_mark, ruby_xml_dtd_free, rxdtd) );
+    break;
+
+/*
+SV *
+new(CLASS, external, system)
+        char * CLASS
+        char * external
+        char * system
+    ALIAS:
+        parse_uri = 1
+    PREINIT:
+        xmlDtdPtr dtd = NULL;
+    CODE:
+        LibXML_error = sv_2mortal(newSVpv("", 0));
+        dtd = xmlParseDTD((const xmlChar*)external, (const xmlChar*)system);
+        if ( dtd == NULL ) {
+            XSRETURN_UNDEF;
+        }
+        xmlSetTreeDoc((xmlNodePtr)dtd, NULL);
+        RETVAL = PmmNodeToSv( (xmlNodePtr) dtd, NULL );
+    OUTPUT:
+        RETVAL
+*/
+
+  case 1:
+
+    rb_scan_args(argc, argv, "10", &dtd_string);
+    buffer = xmlAllocParserInputBuffer(enc);
+    //if ( !buffer) return Qnil
+    new_string = xmlStrdup((xmlChar*)StringValuePtr(dtd_string));
+    xmlParserInputBufferPush(buffer, xmlStrlen(new_string), (const char*)new_string);
+
+    rxdtd = ALLOC(ruby_xml_dtd);
+    rxdtd->dtd = xmlIOParseDTD(NULL, buffer, enc);
+
+    // NOTE: For some reason freeing this InputBuffer causes a segfault! 
+    // xmlFreeParserInputBuffer(buffer); 
+    xmlFree(new_string);
+
+    return( Data_Wrap_Struct(cXMLDtd, ruby_xml_dtd_mark, ruby_xml_dtd_free, rxdtd) );
+
+    break;
+/*
+SV * parse_string(CLASS, str, ...)
+        char * CLASS
+        char * str
+    PREINIT:
+        STRLEN n_a;
+        xmlDtdPtr res;
+        SV * encoding_sv;
+        xmlParserInputBufferPtr buffer;
+        xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
+        xmlChar * new_string;
+        STRLEN len;
+    CODE:
+        LibXML_init_error();
+        if (items > 2) {
+            encoding_sv = ST(2);
+            if (items > 3) {
+                croak("parse_string: too many parameters");
+            }
+            // warn("getting encoding...\n"); 
+            enc = xmlParseCharEncoding(SvPV(encoding_sv, n_a));
+            if (enc == XML_CHAR_ENCODING_ERROR) {
+                croak("Parse of encoding %s failed: %s", SvPV(encoding_sv, n_a), SvPV(LibXML_error, n_a));
+            }
+        }
+        buffer = xmlAllocParserInputBuffer(enc);
+        // buffer = xmlParserInputBufferCreateMem(str, xmlStrlen(str), enc); 
+        if ( !buffer)
+            croak("cant create buffer!\n" );
+
+        new_string = xmlStrdup((const xmlChar*)str);
+        xmlParserInputBufferPush(buffer, xmlStrlen(new_string), (const char*)new_string);
+
+        res = xmlIOParseDTD(NULL, buffer, enc);
+
+        // NOTE: For some reason freeing this InputBuffer causes a segfault! 
+        // xmlFreeParserInputBuffer(buffer); 
+        xmlFree(new_string);
+
+        sv_2mortal( LibXML_error );
+        LibXML_croak_error();
+
+        if (res == NULL) {
+            croak("no DTD parsed!");
+        }
+        RETVAL = PmmNodeToSv((xmlNodePtr)res, NULL);
+    OUTPUT:
+        RETVAL
+ */
+    
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
+  }
+
+  //docobj = ruby_xml_document_new2(cXMLDocument, xmlver);
+  return Qnil;
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_dtd(void) {
+  cXMLDtd = rb_define_class_under(mXML, "Dtd", rb_cObject);
+  rb_define_singleton_method(cXMLDtd, "new", ruby_xml_dtd_initialize, -1);
+  //rb_define_method(cXMLDocument, "xinclude", ruby_xml_document_xinclude, 0);
+}
+

Added: packages-wip/libxml-ruby/trunk/ruby_xml_dtd.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_dtd.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_dtd.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,17 @@
+#ifndef __RUBY_XML_DTD__
+#define __RUBY_XML_DTD__
+
+extern VALUE cXMLDtd;
+
+typedef struct rxp_dtd {
+  xmlDtdPtr dtd;   /* DTD interface */
+  //int data_type;   /* The data type referenced by *data */
+  //void *data;      /* Pointer to an external structure of options */
+  //int is_ptr;      /* Determines if this object owns its data or points to it someplace else */
+  //VALUE xmlver;    /* T_STRING with the xml version */
+} ruby_xml_dtd;
+
+void  ruby_init_xml_dtd(void);
+void  ruby_dtd_free(ruby_xml_dtd *rxdtd);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_input_cbg.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_input_cbg.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_input_cbg.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,167 @@
+
+/* ruby support for custom scheme handlers      */
+/* Author: Martin Povolny (xpovolny at fi.muni.cz) */
+
+#include "libxml.h"
+#include "ruby_xml_input_cbg.h"
+
+static ic_scheme *first_scheme = 0;
+
+int ic_match (char const *filename) {
+    ic_scheme *scheme;
+
+    //fprintf( stderr, "ic_match: %s\n", filename );
+
+    scheme = first_scheme;
+    while (0 != scheme) {
+        if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST scheme->scheme_name, scheme->name_len)) {
+            return 1;
+        }
+        scheme = scheme->next_scheme;
+    }
+    return 0;
+}
+
+void* ic_open (char const *filename) {
+    ic_doc_context *ic_doc;
+    ic_scheme *scheme;
+    VALUE res;
+    
+    scheme = first_scheme;
+    while (0 != scheme) {
+        if (!xmlStrncasecmp(BAD_CAST filename, BAD_CAST scheme->scheme_name, scheme->name_len)) {
+          ic_doc = (ic_doc_context*)malloc( sizeof(ic_doc_context) );
+
+// MUFF         res = rb_funcall( 
+//                  rb_funcall( rb_mKernel, 
+//                              rb_intern("const_get"), 1, 
+//                              rb_str_new2(scheme->class) ),
+//                  rb_intern("document_query"), 1, rb_str_new2(filename) );
+          res = rb_funcall( scheme->class,
+                            rb_intern("document_query"), 
+                            1, 
+                            rb_str_new2(filename) );
+
+          ic_doc->buffer = strdup( StringValuePtr(res) );
+
+          ic_doc->bpos = ic_doc->buffer;
+          ic_doc->remaining = strlen(ic_doc->buffer);
+          return ic_doc;
+        }
+        scheme = scheme->next_scheme;
+    }
+    return 0;
+}
+
+int ic_read (void *context, char *buffer, int len) {
+    ic_doc_context *ic_doc;
+    int ret_len;
+    ic_doc = (ic_doc_context*)context;
+
+    if (len >= ic_doc->remaining) {
+        ret_len =  ic_doc->remaining;
+    } else {
+        ret_len = len;
+    }
+    ic_doc->remaining -= ret_len;
+    strncpy( buffer, ic_doc->bpos, ret_len );
+    ic_doc->bpos += ret_len;
+
+    return ret_len;
+}
+
+int ic_close (void *context) {
+    free( ((ic_doc_context*)context)->buffer );
+    free( context );
+    return 1;
+}
+
+VALUE input_callbacks_register_input_callbacks() {
+    xmlRegisterInputCallbacks( ic_match, ic_open, ic_read, ic_close );
+    return(Qtrue);
+}
+
+VALUE
+input_callbacks_add_scheme (VALUE self, VALUE scheme_name, VALUE class) {
+  ic_scheme *scheme;
+
+  Check_Type(scheme_name, T_STRING);
+  //MUFF Check_Type(class, T_STRING);
+
+  scheme              = (ic_scheme*)malloc(sizeof(ic_scheme));
+  scheme->next_scheme = 0;
+  scheme->scheme_name = strdup(StringValuePtr(scheme_name));  /* TODO alloc, dealloc */
+  scheme->name_len    = strlen(scheme->scheme_name);
+  //MUFF scheme->class       = strdup(StringValuePtr(class));        /* TODO alloc, dealloc */
+  scheme->class       = class;        /* TODO alloc, dealloc */
+
+  //fprintf( stderr, "registered: %s, %d, %s\n", scheme->scheme_name, scheme->name_len, scheme->class );
+  
+  if (0 == first_scheme)
+    first_scheme = scheme;
+  else {
+    ic_scheme *pos;
+    pos = first_scheme;
+    while (0 != pos->next_scheme)
+      pos = pos->next_scheme;
+    pos->next_scheme = scheme;
+  }
+  
+  return(Qtrue);
+}
+
+VALUE
+input_callbacks_remove_scheme (VALUE self, VALUE scheme_name) {
+    char *name;
+    ic_scheme *save_scheme, *scheme;
+
+    Check_Type(scheme_name, T_STRING);
+    name = StringValuePtr(scheme_name);
+
+    if (0 == first_scheme)
+        return Qfalse;
+    
+    /* check the first one */
+    if (!strncmp(name, first_scheme->scheme_name, first_scheme->name_len)) {
+        save_scheme = first_scheme->next_scheme;
+
+        free(first_scheme->scheme_name);
+        //MUFF free(first_scheme->class);
+        free(first_scheme);
+
+        first_scheme = save_scheme;
+        return Qtrue;
+    }
+    
+    scheme = first_scheme;
+    while (0 != scheme->next_scheme) {
+        if ( !strncmp( name, scheme->next_scheme->scheme_name, scheme->next_scheme->name_len ) ) {
+            save_scheme = scheme->next_scheme->next_scheme;
+            
+            free(scheme->next_scheme->scheme_name);
+            //MUFF free(scheme->next_scheme->class);
+            free(scheme->next_scheme);
+
+            scheme->next_scheme = save_scheme;
+            return Qtrue;
+        }
+        scheme = scheme->next_scheme;
+    }
+    return Qfalse;
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_input_callbacks(void) {
+  VALUE cInputCallbacks;
+  cInputCallbacks = rb_define_class_under(mXML, "InputCallbacks", rb_cObject);
+
+  /* Class Methods */
+  rb_define_singleton_method(cInputCallbacks, "register",      input_callbacks_register_input_callbacks, 0);
+  rb_define_singleton_method(cInputCallbacks, "add_scheme",    input_callbacks_add_scheme, 2);
+  rb_define_singleton_method(cInputCallbacks, "remove_scheme", input_callbacks_remove_scheme, 1);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_input_cbg.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_input_cbg.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_input_cbg.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,21 @@
+#ifndef _INPUT_CBG_
+#define _INPUT_CBG_
+
+void ruby_init_input_callbacks(void);
+
+typedef struct ic_doc_context {
+    char *buffer;
+    char *bpos;
+    int remaining;
+} ic_doc_context;
+
+typedef struct ic_scheme {
+    char *scheme_name;
+    //MUFF char *class;
+    VALUE class;
+    int name_len;
+
+    struct ic_scheme *next_scheme;
+} ic_scheme;
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_node.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_node.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_node.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,2139 @@
+/* $Id: ruby_xml_node.c,v 1.3 2006/04/12 12:08:39 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_node.h"
+
+VALUE cXMLNode;
+VALUE eXMLNodeSetNamespace;
+VALUE eXMLNodeFailedModify;
+VALUE eXMLNodeUnknownType;
+
+/*
+ * call-seq:
+ *    node.attribute? => (true|false)
+ * 
+ * Determine whether this is an attribute node,
+ */
+VALUE
+ruby_xml_node_attribute_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_ATTRIBUTE_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.attribute_decl? => (true|false)
+ * 
+ * Determine whether this is an attribute declaration node,
+ */
+VALUE
+ruby_xml_node_attribute_decl_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_ATTRIBUTE_DECL)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.base => "uri"
+ * 
+ * Obtain this node's base URI.
+ */
+VALUE
+ruby_xml_node_base_get(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->doc == NULL)
+    return(Qnil);
+    
+  // TODO some NULL checking, raises ArgumentError in Ruby:
+  //                          ArgumentError: NULL pointer given
+
+  return(rb_str_new2((const char*)xmlNodeGetBase(rxn->node->doc, rxn->node)));
+}
+
+
+// TODO node_base_set should support setting back to nil
+
+/*
+ * call-seq:
+ *    node.base = "uri"
+ * 
+ * Set this node's base URI.
+ */
+VALUE
+ruby_xml_node_base_set(VALUE self, VALUE uri) {
+  ruby_xml_node *node;
+
+  Check_Type(uri, T_STRING);
+  Data_Get_Struct(self, ruby_xml_node, node);
+  if (node->node->doc == NULL)
+    return(Qnil);
+
+  xmlNodeSetBase(node->node, (xmlChar*)StringValuePtr(uri));
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.cdata? => (true|false)
+ * 
+ * Determine whether this is a #CDATA node
+ */
+VALUE
+ruby_xml_node_cdata_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_CDATA_SECTION_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.comment? => (true|false)
+ * 
+ * Determine whether this is a comment node
+ */
+VALUE
+ruby_xml_node_comment_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_COMMENT_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node << ("string" | node)
+ * 
+ * Add the specified string or XML::Node to this node's
+ * content.
+ */
+VALUE
+ruby_xml_node_content_add(VALUE self, VALUE obj) {
+  ruby_xml_node *node;
+  VALUE str;
+
+  Data_Get_Struct(self, ruby_xml_node, node);
+  if (rb_obj_is_kind_of(obj, cXMLNode)) {
+    return(ruby_xml_node_child_set(self, obj));
+  } else if (TYPE(obj) == T_STRING) {
+    xmlNodeAddContent(node->node, (xmlChar*)StringValuePtr(obj));
+    return(obj);
+  } else {
+    str = rb_obj_as_string(obj);
+    if (NIL_P(str) || TYPE(str) != T_STRING)
+      rb_raise(rb_eTypeError, "invalid argument: must be string or XML::Node");
+
+    xmlNodeAddContent(node->node, (xmlChar*)StringValuePtr(str));
+    return(obj);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    node.content => "string"
+ * 
+ * Obtain this node's content as a string.
+ */
+VALUE
+ruby_xml_node_content_get(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlChar *content;
+  VALUE out;
+  
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  content = xmlNodeGetContent(rxn->node);
+  out = rb_str_new2((const char *) content);
+  xmlFree(content);
+ 
+  return out;
+}
+
+/*
+ * call-seq:
+ *    node.content = "string"
+ * 
+ * Set this node's content to the specified string.
+ */ 
+VALUE
+ruby_xml_node_content_set(VALUE self, VALUE content) {
+  ruby_xml_node *node;
+
+  Check_Type(content, T_STRING);
+  Data_Get_Struct(self, ruby_xml_node, node);
+  xmlNodeSetContent(node->node, (xmlChar*)StringValuePtr(content));
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.content_stripped => "string"
+ * 
+ * Obtain this node's stripped content.
+ * 
+ * *Deprecated*: Stripped content can be obtained via the
+ * +content+ method.
+ */
+VALUE
+ruby_xml_node_content_stripped_get(VALUE self) {
+  ruby_xml_node *rxn;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->content == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)xmlNodeGetContent(rxn->node)));
+}
+
+////////////////////////////////////////////////////
+// TODO This whole child thing seems to work in some odd ways.
+//      Try setting child= to a node with multiple children,
+//      then get it back through child= .
+      
+/*
+ * call-seq:
+ *    node.child => node
+ * 
+ * Obtain this node's first child node, if any.
+ */
+VALUE
+ruby_xml_node_child_get(VALUE self) {
+  ruby_xml_node *node;
+  xmlNodePtr tmp;
+
+  Data_Get_Struct(self, ruby_xml_node, node);
+
+  switch (node->node->type) {
+  case XML_ELEMENT_NODE:
+  case XML_ENTITY_REF_NODE:
+  case XML_ENTITY_NODE:
+  case XML_PI_NODE:
+  case XML_COMMENT_NODE:
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+  case XML_DTD_NODE:
+    tmp = node->node->children;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) node->node;
+      tmp = attr->children;
+      break;
+    }
+  default:
+    tmp = NULL;
+    break;
+  }
+
+  if (tmp == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, node->xd, tmp));
+}
+
+
+/*
+ * call-seq:
+ *    node.child? => (true|false)
+ * 
+ * Determine whether this node has at least one child.
+ */
+VALUE
+ruby_xml_node_child_q(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlNodePtr node;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  node = NULL;
+  switch (rxn->node->type) {
+  case XML_ELEMENT_NODE:
+  case XML_ENTITY_REF_NODE:
+  case XML_ENTITY_NODE:
+  case XML_PI_NODE:
+  case XML_COMMENT_NODE:
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+  case XML_DTD_NODE:
+    node = rxn->node->children;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      node = attr->children;
+      break;
+    }
+  default:
+    node = NULL;
+  }
+
+  if (node == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.child = node
+ * 
+ * Set a child node for this node.
+ */
+VALUE
+ruby_xml_node_child_set(VALUE self, VALUE rnode) {
+  ruby_xml_node *cnode, *pnode;
+  xmlNodePtr ret;
+
+  if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
+    rb_raise(rb_eTypeError, "Must pass an XML::Node object");
+
+  Data_Get_Struct(self,  ruby_xml_node, pnode);
+  Data_Get_Struct(rnode, ruby_xml_node, cnode);
+
+  ret = xmlAddChild(pnode->node, cnode->node);
+  if (ret == NULL)
+    rb_raise(eXMLNodeFailedModify, "unable to add a child to the document");
+
+  ruby_xml_node_set_ptr(rnode, 1);
+  return(ruby_xml_node_new2(cXMLNode, pnode->xd, ret));
+}
+
+////////////////////////////////////////////////
+// TODO new Documents seem to be created quite readily...
+
+/*
+ * call-seq:
+ *    node.doc => document
+ * 
+ * Obtain the XML::Document this node belongs to.
+ */
+VALUE
+ruby_xml_node_doc(VALUE self) {
+  ruby_xml_document *rxd;
+  ruby_xml_node *rxn;
+  xmlDocPtr doc;
+  VALUE docobj;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+    doc = NULL;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      doc = attr->doc;
+      break;
+    }
+  case XML_NAMESPACE_DECL:
+    doc = NULL;
+    break;
+  default:
+    doc = rxn->node->doc;
+    break;
+  }
+
+  if (doc == NULL)
+    return(Qnil);
+
+  docobj = ruby_xml_document_new(cXMLDocument, doc);
+  Data_Get_Struct(docobj, ruby_xml_document, rxd);
+  rxd->is_ptr = 1;
+  return(docobj);
+}
+
+
+/*
+ * call-seq:
+ *    node.docbook? => (true|false)
+ * 
+ * Determine whether this is a docbook node.
+ */
+VALUE
+ruby_xml_node_docbook_doc_q(VALUE self) {
+#ifdef LIBXML_DOCB_ENABLED
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_DOCB_DOCUMENT_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+#else
+  rb_warn("libxml compiled without docbook support");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    node.doctype? => (true|false)
+ * 
+ * Determine whether this is a DOCTYPE node.
+ */
+VALUE
+ruby_xml_node_doctype_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_DOCUMENT_TYPE_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.document? => (true|false)
+ * 
+ * Determine whether this is a document node.
+ */
+VALUE
+ruby_xml_node_document_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_DOCUMENT_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.dtd? => (true|false)
+ * 
+ * Determine whether this is a DTD node.
+ */
+VALUE
+ruby_xml_node_dtd_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_DTD_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.dump => (true|nil)
+ * 
+ * Dump this node to stdout.
+ */
+VALUE
+ruby_xml_node_dump(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlBufferPtr buf;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  if (rxn->node->doc == NULL)
+    return(Qnil);
+
+  buf = xmlBufferCreate();
+  xmlNodeDump(buf, rxn->node->doc, rxn->node, 0, 1);
+  xmlBufferDump(stdout, buf);
+  xmlBufferFree(buf);
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.debug_dump => (true|nil)
+ * 
+ * Dump this node to stdout, including any debugging
+ * information.
+ */
+VALUE
+ruby_xml_node_debug_dump(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  if (rxn->node->doc == NULL)
+    return(Qnil);
+
+  xmlElemDump(stdout, rxn->node->doc, rxn->node);
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.element? => (true|false)
+ * 
+ * Determine whether this is an element node.
+ */
+VALUE
+ruby_xml_node_element_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_ELEMENT_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.element_decl? => (true|false)
+ * 
+ * Determine whether this is an element declaration node.
+ */
+VALUE
+ruby_xml_node_element_decl_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_ELEMENT_DECL)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.empty? => (true|false)
+ * 
+ * Determine whether this node is empty.
+ */
+VALUE
+ruby_xml_node_empty_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node == NULL)
+    return(Qnil);
+
+  return((xmlIsBlankNode(rxn->node) == 1) ? Qtrue : Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.entity? => (true|false)
+ * 
+ * Determine whether this is an entity node.
+ */
+VALUE
+ruby_xml_node_entity_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_ENTITY_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.entity_ref? => (true|false)
+ * 
+ * Determine whether this is an entity reference node.
+ */
+VALUE
+ruby_xml_node_entity_ref_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_ENTITY_REF_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+VALUE ruby_xml_node_to_s(VALUE self);
+
+/*
+ * call-seq:
+ *    node.eql?(other_node) => (true|false)
+ * 
+ * Test equality between the two nodes. Equality is determined based
+ * on the XML representation of the nodes.
+ */
+VALUE
+ruby_xml_node_eql_q(VALUE self, VALUE other) {
+  // TODO this isn't the best way to handle this
+  ruby_xml_node *rxn, *orxn;  
+  VALUE thisxml, otherxml;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  Data_Get_Struct(other, ruby_xml_node, orxn);
+  thisxml = ruby_xml_node_to_s(self);
+  otherxml = ruby_xml_node_to_s(other);
+  
+  return(rb_funcall(thisxml, rb_intern("=="), 1, otherxml));
+}
+
+
+/*
+ * call-seq:
+ *    node.find(xpath_expr, namespace = [any]) => nodeset
+ * 
+ * Find nodes matching the specified xpath expression, optionally
+ * using the specified namespaces. Returns an XML::Node::Set.
+ */
+VALUE
+ruby_xml_node_find(int argc, VALUE *argv, VALUE self) {
+  int i, vargc;
+  VALUE *vargv;
+
+  if (argc > 2 || argc < 1)
+    rb_raise(rb_eArgError, "wrong number of arguments (need 1 or 2)");
+
+  vargc = argc + 1;
+  vargv = ALLOC_N(VALUE, vargc + 1);
+  vargv[0] = self;
+  for (i = 0; i<argc; i++)
+    vargv[i + 1] = argv[i];
+
+  return(ruby_xml_xpath_find2(vargc, vargv));
+}
+
+/*
+ * call-seq:
+ *    node.find_first(xpath_expr, namespace = [any]) => nodeset
+ *
+ * Find the first node matching the specified xpath expression, optionally
+ * using the specified namespaces. Returns an XML::Node.
+ */
+VALUE
+ruby_xml_node_find_first(int argc, VALUE *argv, VALUE self) {
+  VALUE ns = ruby_xml_node_find(argc, argv, self);
+  ruby_xml_node_set *rxnset;
+
+  Data_Get_Struct(ns, ruby_xml_node_set, rxnset);
+  if (rxnset->node_set == NULL || rxnset->node_set->nodeNr < 1)
+    return(Qnil);
+
+  VALUE nodeobj;
+  switch(rxnset->node_set->nodeTab[0]->type) {
+    case XML_ATTRIBUTE_NODE:
+      nodeobj = ruby_xml_attr_new2(cXMLAttr, rxnset->xd, (xmlAttrPtr)rxnset->node_set->nodeTab[0]);
+      break;
+    default:
+      nodeobj = ruby_xml_node_new2(cXMLNode, rxnset->xd, rxnset->node_set->nodeTab[0]);
+  }
+
+  return(nodeobj);
+}
+
+
+/*
+ * call-seq:
+ *    node.fragment? => (true|false)
+ * 
+ * Determine whether this node is a fragment.
+ */
+VALUE
+ruby_xml_node_fragment_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_DOCUMENT_FRAG_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+void ruby_xml_node_free(ruby_xml_node *rxn) {
+  if (rxn->node != NULL && !rxn->is_ptr) {
+    xmlUnlinkNode(rxn->node);
+    xmlFreeNode(rxn->node);
+    rxn->node = NULL;
+  }
+
+  free(rxn);
+}
+
+
+/*
+ * call-seq:
+ *    node.hash => fixnum
+ * 
+ * Returns the hash-code for this node. This is the hash of the XML
+ * representation in order to be consistent with eql.
+ */
+VALUE
+ruby_xml_node_hash(VALUE self) {
+  ruby_xml_node *rxn;
+  VALUE thisxml;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  thisxml = ruby_xml_node_to_s(self);
+  
+  return(rb_funcall(thisxml, rb_intern("hash"), 0));
+}
+
+
+/*
+ * call-seq:
+ *    node.html_doc? => (true|false)
+ * 
+ * Determine whether this node is an html document node.
+ */
+VALUE
+ruby_xml_node_html_doc_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_HTML_DOCUMENT_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Node.new(name, content = nil) => node
+ * 
+ * Create a new node with the specified name, optionally setting
+ * the node's content.
+ */
+VALUE
+ruby_xml_node_initialize(int argc, VALUE *argv, VALUE class) {
+  ruby_xml_node *rxn;
+  VALUE name, node, str;
+
+  str = Qnil;
+
+  switch(argc) {
+  case 2:
+    switch (TYPE(str)) {
+    case T_STRING:
+      str = argv[1];
+      break;
+    default:
+      str = rb_obj_as_string(argv[1]);
+      if (NIL_P(str))
+	Check_Type(str, T_STRING);
+      break;
+    }
+
+    /* Intentionally fall through to case 1: as a way of setting up
+     * the object.  Sneaky, but effective.  Probably should use a goto
+     * instead. */
+  case 1:
+    name = argv[0];
+    Check_Type(name, T_STRING);
+    node = ruby_xml_node_new(class, NULL);
+    Data_Get_Struct(node, ruby_xml_node, rxn);
+    rxn->node = xmlNewNode(NULL, (xmlChar*)StringValuePtr(name));
+    if (rxn->node == NULL)
+      return(Qnil);
+
+    if (!NIL_P(str))
+      ruby_xml_node_content_set(node, str);
+
+    break;
+
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
+  }
+
+  return(node);
+}
+
+
+/*
+ * call-seq:
+ *    node.lang => "string"
+ * 
+ * Obtain the language set for this node, if any.
+ * This is set in XML via the xml:lang attribute.
+ */
+VALUE
+ruby_xml_node_lang_get(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlChar *lang;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  lang = xmlNodeGetLang(rxn->node);
+
+  if (lang == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)lang));
+}
+
+
+// TODO node_lang_set should support setting back to nil
+
+/*
+ * call-seq:
+ *    node.lang = "string"
+ * 
+ * Set the language for this node. This affects the value
+ * of the xml:lang attribute.
+ */
+VALUE
+ruby_xml_node_lang_set(VALUE self, VALUE lang) {
+  ruby_xml_node *node;
+
+  Check_Type(lang, T_STRING);
+  Data_Get_Struct(self, ruby_xml_node, node);
+  xmlNodeSetLang(node->node, (xmlChar*)StringValuePtr(lang));
+
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.last => node
+ * 
+ * Obtain the last child node of this node, if any.
+ */
+VALUE
+ruby_xml_node_last_get(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlNodePtr node;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_ELEMENT_NODE:
+  case XML_ENTITY_REF_NODE:
+  case XML_ENTITY_NODE:
+  case XML_PI_NODE:
+  case XML_COMMENT_NODE:
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+  case XML_DTD_NODE:
+    node = rxn->node->last;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      node = attr->last;
+    }
+  default:
+    node = NULL;
+    break;
+  }
+
+  if (node == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
+}
+
+
+/*
+ * call-seq:
+ *    node.last? => (true|false)
+ * 
+ * Determine whether this node has a last child node.
+ */
+VALUE
+ruby_xml_node_last_q(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlNodePtr node;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_ELEMENT_NODE:
+  case XML_ENTITY_REF_NODE:
+  case XML_ENTITY_NODE:
+  case XML_PI_NODE:
+  case XML_COMMENT_NODE:
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+  case XML_DTD_NODE:
+    node = rxn->node->last;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      node = attr->last;
+    }
+  default:
+    node = NULL;
+    break;
+  }
+
+  if (node == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.line_num => num
+ * 
+ * Obtain the line number (in the XML document) that this
+ * node was read from. If +default_line_numbers+ is set
+ * false (the default), this method returns zero.
+ */
+VALUE
+ruby_xml_node_line_num(VALUE self) {
+  ruby_xml_node *rxn;
+  long line_num;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  if (!xmlLineNumbersDefaultValue)
+    rb_warn("Line numbers were not retained: use XML::Parser::default_line_numbers=true");
+
+  line_num = xmlGetLineNo(rxn->node);
+  if (line_num == -1)
+    return(Qnil);
+  else
+    return(INT2NUM((long)line_num));
+}
+
+
+/*
+ * call-seq:
+ *    node.xlink? => (true|false)
+ * 
+ * Determine whether this node is an xlink node.
+ */
+VALUE
+ruby_xml_node_xlink_q(VALUE self) {
+  ruby_xml_node *node;
+  ruby_xml_document *doc;
+  xlinkType xlt;
+
+  Data_Get_Struct(self, ruby_xml_node, node);
+  Data_Get_Struct(node->xd, ruby_xml_document, doc);
+  xlt = xlinkIsLink(doc->doc, node->node);
+
+  if (xlt == XLINK_TYPE_NONE)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.xlink_type => num
+ * 
+ * Obtain the type identifier for this xlink, if applicable.
+ * If this is not an xlink node (see +xlink?+), will return
+ * nil.
+ */
+VALUE
+ruby_xml_node_xlink_type(VALUE self) {
+  ruby_xml_node *node;
+  ruby_xml_document *doc;
+  xlinkType xlt;
+
+  Data_Get_Struct(self, ruby_xml_node, node);
+  Data_Get_Struct(node->xd, ruby_xml_document, doc);
+  xlt = xlinkIsLink(doc->doc, node->node);
+
+  if (xlt == XLINK_TYPE_NONE)
+    return(Qnil);
+  else
+    return(INT2NUM(xlt));
+}
+
+
+/*
+ * call-seq:
+ *    node.xlink_type_name => "string"
+ * 
+ * Obtain the type name for this xlink, if applicable.
+ * If this is not an xlink node (see +xlink?+), will return
+ * nil.
+ */
+VALUE
+ruby_xml_node_xlink_type_name(VALUE self) {
+  ruby_xml_node *node;
+  ruby_xml_document *doc;
+  xlinkType xlt;
+
+  Data_Get_Struct(self, ruby_xml_node, node);
+  Data_Get_Struct(node->xd, ruby_xml_document, doc);
+  xlt = xlinkIsLink(doc->doc, node->node);
+
+  switch(xlt) {
+  case XLINK_TYPE_NONE:
+    return(Qnil);
+  case XLINK_TYPE_SIMPLE:
+    return(rb_str_new2("simple"));
+  case XLINK_TYPE_EXTENDED:
+    return(rb_str_new2("extended"));
+  case XLINK_TYPE_EXTENDED_SET:
+    return(rb_str_new2("extended_set"));
+  default:
+    rb_fatal("Unknowng xlink type, %d", xlt);
+  }
+}
+
+
+static void
+ruby_xml_node_mark(ruby_xml_node *rxn) {
+  if (rxn == NULL) return;
+  if (!NIL_P(rxn->xd)) rb_gc_mark(rxn->xd);
+}
+
+
+/*
+ * call-seq:
+ *    node.name => "string"
+ * 
+ * Obtain this node's name.
+ */
+VALUE
+ruby_xml_node_name_get(VALUE self) {
+  ruby_xml_node *rxn;
+  const xmlChar *name;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+    {
+      xmlDocPtr doc = (xmlDocPtr) rxn->node;
+      name = doc->URL;
+      break;
+    }
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      name = attr->name;
+      break;
+    }
+  case XML_NAMESPACE_DECL:
+    {
+      xmlNsPtr ns = (xmlNsPtr) rxn->node;
+      name = ns->prefix;
+      break;
+    }
+  default:
+    name = rxn->node->name;
+    break;
+  }
+
+  if (rxn->node->name == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)name));
+}
+
+
+/*
+ * call-seq:
+ *    node.name = "string"
+ * 
+ * Set this node's name.
+ */
+VALUE
+ruby_xml_node_name_set(VALUE self, VALUE name) {
+  ruby_xml_node *node;
+
+  Check_Type(name, T_STRING);
+  Data_Get_Struct(self, ruby_xml_node, node);
+  xmlNodeSetName(node->node, (xmlChar*)StringValuePtr(name));
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.namespace => [namespace, ..., namespace]
+ * 
+ * Obtain an array of +XML::NS+ objects representing
+ * this node's xmlns attributes
+ */
+VALUE
+ruby_xml_node_namespace_get(VALUE self) {
+  ruby_xml_node *node;
+  xmlNsPtr *nsList, *cur;
+  VALUE arr, ns;
+
+  Data_Get_Struct(self, ruby_xml_node, node);
+  if (node->node == NULL)
+    return(Qnil);
+
+  nsList = xmlGetNsList(node->node->doc, node->node);
+
+  if (nsList == NULL)
+    return(Qnil);
+
+  arr = rb_ary_new();
+  for (cur = nsList; *cur != NULL; cur++) {
+    ns = ruby_xml_ns_new2(cXMLNS, node->xd, *cur);
+    if (ns == Qnil)
+      continue;
+    else
+      rb_ary_push(arr, ns);
+  }
+  xmlFree(nsList);
+
+  return(arr);
+}
+
+
+/*
+ * call-seq:
+ *    node.namespace_node => namespace.
+ * 
+ * Obtain this node's namespace node.
+ */
+VALUE
+ruby_xml_node_namespace_get_node(VALUE self) {
+  ruby_xml_node *node;
+
+  Data_Get_Struct(self, ruby_xml_node, node);
+  if (node->node->ns == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_ns_new2(cXMLNS, node->xd, node->node->ns));
+}
+
+// TODO namespace_set can take varargs (in fact, must if used
+//      with strings), but I cannot see how you can call 
+//      that version, apart from with 'send'
+//
+//      Would sure be nice to support foo.namespace['foo'] = 'bar'
+//      but maybe that's not practical...
+
+/*
+ * call-seq:
+ *    node.namespace = namespace
+ * 
+ * Add the specified XML::NS object to this node's xmlns attributes.
+ */
+VALUE
+ruby_xml_node_namespace_set(int argc, VALUE *argv, VALUE self) {
+  VALUE rns, rprefix;
+  ruby_xml_node *rxn;
+  ruby_xml_ns *rxns;
+  xmlNsPtr ns;
+  char *cp, *href;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  switch (argc) {
+  case 1:
+    rns = argv[0];
+    if (TYPE(rns) == T_STRING) {
+      cp = strchr(StringValuePtr(rns), (int)':');
+      if (cp == NULL) {
+	rprefix = rns;
+	href = NULL;
+      } else {
+	rprefix = rb_str_new(StringValuePtr(rns), (int)((long)cp - (long)StringValuePtr(rns)));
+	href = &cp[1]; /* skip the : */
+      }
+    } else if (rb_obj_is_kind_of(rns, cXMLNS) == Qtrue) {
+      Data_Get_Struct(self, ruby_xml_ns, rxns);
+      xmlSetNs(rxn->node, rxns->ns);
+      return(rns);
+    } else
+      rb_raise(rb_eTypeError, "must pass a string or an XML::Ns object");
+
+    /* Fall through to next case because when argc == 1, we need to
+     * manually setup the additional args unless the arg passed is of
+     * cXMLNS type */
+  case 2:
+    /* Don't want this code run in the fall through case */
+    if (argc == 2) {
+      rprefix = argv[0];
+      href = StringValuePtr(argv[1]);
+    }
+
+    ns = xmlNewNs(rxn->node, (xmlChar*)href, (xmlChar*)StringValuePtr(rprefix));
+    if (ns == NULL)
+      rb_raise(eXMLNodeSetNamespace, "unable to set the namespace");
+    else
+      return(ruby_xml_ns_new2(cXMLNS, rxn->xd, ns));
+    break;
+
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
+  }
+
+  /* can't get here */
+  return(Qnil);
+}
+
+
+/*
+ * call-seq:
+ *    node.namespace? => (true|false)
+ * 
+ * Determine whether this node *is* (not has) a namespace
+ * node.
+ */
+VALUE
+ruby_xml_node_namespace_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_NAMESPACE_DECL)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+VALUE
+ruby_xml_node_new(VALUE class, xmlNodePtr node) {
+  ruby_xml_node *rxn;
+
+  rxn = ALLOC(ruby_xml_node);
+  rxn->is_ptr = 0;
+  rxn->node = node;
+  rxn->xd = Qnil;
+  return(Data_Wrap_Struct(class, ruby_xml_node_mark,
+			  ruby_xml_node_free, rxn));
+}
+
+
+VALUE
+ruby_xml_node_new2(VALUE class, VALUE xd, xmlNodePtr node) {
+  ruby_xml_node *rxn;
+
+  rxn = ALLOC(ruby_xml_node);
+  rxn->is_ptr = 1;
+  rxn->node = node;
+  if (NIL_P(xd))
+    rxn->xd = Qnil;
+  else
+    rxn->xd = xd;
+  return(Data_Wrap_Struct(class, ruby_xml_node_mark,
+			  ruby_xml_node_free, rxn));
+}
+
+
+/*
+ * call-seq:
+ *    node.next => node
+ * 
+ * Obtain the next sibling node, if any.
+ */
+VALUE
+ruby_xml_node_next_get(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlNodePtr node;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+    node = NULL;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      node = (xmlNodePtr) attr->next;
+      break;
+    }
+  case XML_NAMESPACE_DECL:
+    {
+      xmlNsPtr ns = (xmlNsPtr) rxn->node;
+      node = (xmlNodePtr) ns->next;
+      break;
+    }
+  default:
+    node = rxn->node->next;
+    break;
+  }
+
+  if (node == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
+}
+
+
+/*
+ * call-seq:
+ *    node.next? => (true|false)
+ * 
+ * Determine whether this node has a next sibling.
+ */
+VALUE
+ruby_xml_node_next_q(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlNodePtr node;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+    node = NULL;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      node = (xmlNodePtr) attr->next;
+      break;
+    }
+  case XML_NAMESPACE_DECL:
+    {
+      xmlNsPtr ns = (xmlNsPtr) rxn->node;
+      node = (xmlNodePtr) ns->next;
+      break;
+    }
+  default:
+    node = rxn->node->next;
+    break;
+  }
+
+  if (node == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.notation? => (true|false)
+ * 
+ * Determine whether this is a notation node
+ */
+VALUE
+ruby_xml_node_notation_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_NOTATION_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.ns? => (true|false)
+ * 
+ * Determine whether this node is a namespace node.
+ */
+VALUE
+ruby_xml_node_ns_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->ns == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.ns_def => namespace
+ * 
+ * Obtain this node's default namespace.
+ */
+VALUE
+ruby_xml_node_ns_def_get(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->nsDef == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_ns_new2(cXMLNS, rxn->xd, rxn->node->nsDef));
+}
+
+
+/*
+ * call-seq:
+ *    node.ns_def? => (true|false)
+ * 
+ * Obtain an array of +XML::NS+ objects representing
+ * this node's xmlns attributes
+ */
+VALUE
+ruby_xml_node_ns_def_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->nsDef == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.parent => node
+ * 
+ * Obtain this node's parent node, if any.
+ */
+VALUE
+ruby_xml_node_parent_get(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlNodePtr node;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_DOCUMENT_NODE:
+  case XML_HTML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+    node = NULL;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      node = attr->parent;
+    }
+  case XML_ENTITY_DECL:
+  case XML_NAMESPACE_DECL:
+  case XML_XINCLUDE_START:
+  case XML_XINCLUDE_END:
+    node = NULL;
+    break;
+  default:
+    node = rxn->node->parent;
+    break;
+  }
+
+  if (node == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
+}
+
+
+/*
+ * call-seq:
+ *    node.parent? => (true|false)
+ * 
+ * Determine whether this node has a parent node.
+ */
+VALUE
+ruby_xml_node_parent_q(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlNodePtr node;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_DOCUMENT_NODE:
+  case XML_HTML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+    node = NULL;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      node = attr->parent;
+    }
+  case XML_ENTITY_DECL:
+  case XML_NAMESPACE_DECL:
+  case XML_XINCLUDE_START:
+  case XML_XINCLUDE_END:
+    node = NULL;
+    break;
+  default:
+    node = rxn->node->parent;
+    break;
+  }
+
+  if (node == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.path => path
+ * 
+ * Obtain this node's path.
+ */
+VALUE
+ruby_xml_node_path(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlChar *path;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  path = xmlGetNodePath(rxn->node);
+
+  if (path == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)path));
+}
+
+
+/*
+ * call-seq:
+ *    node.pi? => (true|false)
+ * 
+ * Determine whether this is a processing instruction node.
+ */
+VALUE
+ruby_xml_node_pi_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_PI_NODE)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.pointer => node_set
+ * 
+ * Evaluates an XPointer expression relative to this node.
+ */
+VALUE
+ruby_xml_node_pointer(VALUE self, VALUE xptr_str) {
+  return(ruby_xml_xpointer_point2(self, xptr_str));
+}
+
+
+/*
+ * call-seq:
+ *    node.prev => node
+ * 
+ * Obtain the previous sibling, if any.
+ */
+VALUE
+ruby_xml_node_prev_get(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlNodePtr node;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+  case XML_NAMESPACE_DECL:
+    node = NULL;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      node = (xmlNodePtr) attr->next;
+    }
+    break;
+  default:
+    node = rxn->node->next;
+    break;
+  }
+
+  if (node == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode, rxn->xd, node));
+}
+
+
+/*
+ * call-seq:
+ *    node.prev? => (true|false)
+ * 
+ * Determines whether this node has a previous sibling node.
+ */
+VALUE
+ruby_xml_node_prev_q(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlNodePtr node;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch (rxn->node->type) {
+  case XML_DOCUMENT_NODE:
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+#endif
+  case XML_HTML_DOCUMENT_NODE:
+  case XML_NAMESPACE_DECL:
+    node = NULL;
+    break;
+  case XML_ATTRIBUTE_NODE:
+    {
+      xmlAttrPtr attr = (xmlAttrPtr) rxn->node;
+      node = (xmlNodePtr) attr->next;
+    }
+    break;
+  default:
+    node = rxn->node->next;
+    break;
+  }
+
+  if (node == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.property("name") => "string"
+ *    node["name"]          => "string"
+ * 
+ * Obtain the named property.
+ */
+VALUE
+ruby_xml_node_property_get(VALUE self, VALUE prop) {
+  ruby_xml_node *rxn;
+  xmlChar *p;
+  VALUE r;
+  
+  Check_Type(prop, T_STRING);
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  p = xmlGetProp(rxn->node, (xmlChar*)StringValuePtr(prop));
+
+  if (p == NULL)
+    r = Qnil;
+  else {
+    r = rb_str_new2((const char*)p);
+    xmlFree(p);
+  }
+  
+  return r;
+}
+
+
+/*
+ * call-seq:
+ *    node["name"] = "string"
+ * 
+ * Set the named property.
+ */
+VALUE
+ruby_xml_node_property_set(VALUE self, VALUE key, VALUE val) {
+  ruby_xml_node *node;
+  ruby_xml_attr *rxa;
+  xmlAttrPtr attr;
+  VALUE rattr;
+
+  Data_Get_Struct(self, ruby_xml_node, node);
+  Check_Type(key, T_STRING);
+  
+  if( val == Qnil ) {
+    attr = xmlSetProp(node->node, (xmlChar*)StringValuePtr(key), NULL);
+    xmlRemoveProp( attr );
+    return Qnil;
+  } else {
+    Check_Type(val, T_STRING);
+  }
+  
+  attr = xmlSetProp(node->node, (xmlChar*)StringValuePtr(key), (xmlChar*)StringValuePtr(val));
+  if (attr == NULL) {
+    attr = xmlNewProp(node->node, (xmlChar*)StringValuePtr(key), (xmlChar*)StringValuePtr(val));
+    if (attr == NULL)
+      return(Qnil);
+  }
+  rattr = ruby_xml_attr_new(cXMLAttr, node->xd, attr);
+  Data_Get_Struct(rattr, ruby_xml_attr, rxa);
+  rxa->is_ptr = 1;
+  return(rattr);
+}
+
+
+/*
+ * call-seq:
+ *    node.properties => attributes
+ * 
+ * Returns the +XML::Attr+ for this node. 
+ */
+VALUE
+ruby_xml_node_properties_get(VALUE self) {
+  ruby_xml_node *node;
+  xmlAttrPtr attr;
+
+  Data_Get_Struct(self, ruby_xml_node, node);
+
+  if (node->node->type == XML_ELEMENT_NODE) {
+    attr = node->node->properties;
+    return(ruby_xml_attr_new2(cXMLAttr, node->xd, attr));
+  } else {
+    return(Qnil);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    node.properties? => (true|false)
+ * 
+ * Determine whether this node has properties
+ * (attributes).
+ */
+VALUE
+ruby_xml_node_properties_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_ELEMENT_NODE && rxn->node->properties != NULL)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+*    node.remove! => nil
+*
+* Removes this node from it's parent.
+*/
+VALUE
+ruby_xml_node_remove_ex(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  xmlUnlinkNode(rxn->node);
+    return(Qnil);
+}
+
+
+/*
+ * call-seq:
+ *    node.search_href => namespace
+ * 
+ * Search for a namespace by href.
+ */
+VALUE
+ruby_xml_node_search_href(VALUE self, VALUE href) {
+  ruby_xml_document *doc;
+  ruby_xml_node *node;
+
+  Check_Type(href, T_STRING);
+  Data_Get_Struct(self, ruby_xml_node, node);
+  Data_Get_Struct(node->xd, ruby_xml_document, doc);
+  return(ruby_xml_ns_new2(cXMLNS, node->xd,
+			  xmlSearchNsByHref(doc->doc, node->node,
+					    (xmlChar*)StringValuePtr(href))));
+}
+
+
+/*
+ * call-seq:
+ *    node.search_ns => namespace
+ * 
+ * Search for a namespace by namespace.
+ */
+VALUE
+ruby_xml_node_search_ns(VALUE self, VALUE ns) {
+  ruby_xml_document *doc;
+  ruby_xml_node *node;
+
+  Check_Type(ns, T_STRING);
+  Data_Get_Struct(self, ruby_xml_node, node);
+  Data_Get_Struct(node->xd, ruby_xml_document, doc);
+  return(ruby_xml_ns_new2(cXMLNS, node->xd,
+			  xmlSearchNs(doc->doc, node->node,
+					    (xmlChar*)StringValuePtr(ns))));
+}
+
+
+VALUE
+ruby_xml_node_set_ptr(VALUE node, int is_ptr) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(node, ruby_xml_node, rxn);
+  rxn->is_ptr = is_ptr;
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    node.sibling(node) => node
+ * 
+ * Add the specified node as a sibling of this node.
+ */
+VALUE
+ruby_xml_node_sibling_set(VALUE self, VALUE rnode) {
+  ruby_xml_node *cnode, *pnode;
+  xmlNodePtr ret;
+
+  if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
+    rb_raise(rb_eTypeError, "Must pass an XML::Node object");
+
+  Data_Get_Struct(self,  ruby_xml_node, pnode);
+  Data_Get_Struct(rnode, ruby_xml_node, cnode);
+
+  ret = xmlAddSibling(pnode->node, cnode->node);
+  if (ret == NULL)
+    rb_raise(eXMLNodeFailedModify, "unable to add a sibling to the document");
+
+  cnode->is_ptr = 1;
+  return(ruby_xml_node_new2(cXMLNode, pnode->xd, ret));
+}
+
+
+/*
+ * call-seq:
+ *    node.space_preserve => (true|false)
+ * 
+ * Determine whether this node preserves whitespace.
+ */
+VALUE
+ruby_xml_node_space_preserve_get(VALUE self) {
+  ruby_xml_node *rxn;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  return(INT2NUM(xmlNodeGetSpacePreserve(rxn->node)));
+}
+
+
+/*
+ * call-seq:
+ *    node.space_preserve = true|false
+ * 
+ * Control whether this node preserves whitespace.
+ */
+VALUE
+ruby_xml_node_space_preserve_set(VALUE self, VALUE bool) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  if (TYPE(bool) == T_FALSE)
+    xmlNodeSetSpacePreserve(rxn->node, 1);
+  else
+    xmlNodeSetSpacePreserve(rxn->node, 0);
+
+  return(Qnil);
+}
+
+
+/*
+ * call-seq:
+ *    node.text? => (true|false)
+ * 
+ * Determine whether this node has text.
+ */
+VALUE
+ruby_xml_node_text_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node == NULL)
+    return(Qnil);
+
+  return((xmlNodeIsText(rxn->node) == 1) ? Qtrue : Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.to_s => "string"
+ * 
+ * Coerce this node to a string representation of
+ * it's XML.
+ */
+VALUE
+ruby_xml_node_to_s(VALUE self) {
+  ruby_xml_node *rxn;
+  xmlBufferPtr buf;
+  VALUE result;
+
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  buf = xmlBufferCreate();
+  xmlNodeDump(buf, rxn->node->doc, rxn->node, 0, 1);
+  result = rb_str_new2((const char*)buf->content);
+  
+  xmlBufferFree(buf);
+  return result;
+}
+
+
+/*
+ * call-seq:
+ *    node.type => num
+ * 
+ * Obtain this node's type identifier.
+ */
+VALUE
+ruby_xml_node_type(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  return(INT2NUM(rxn->node->type));
+}
+
+
+/*
+ * call-seq:
+ *    node.type_name => num
+ * 
+ * Obtain this node's type name.
+ */
+VALUE
+ruby_xml_node_type_name(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  switch(rxn->node->type) {
+  case XML_ELEMENT_NODE:
+    return(rb_str_new2("element"));
+  case XML_ATTRIBUTE_NODE:
+    return(rb_str_new2("attribute"));
+  case XML_TEXT_NODE:
+    return(rb_str_new2("text"));
+  case XML_CDATA_SECTION_NODE:
+    return(rb_str_new2("cdata"));
+  case XML_ENTITY_REF_NODE:
+    return(rb_str_new2("entity_ref"));
+  case XML_ENTITY_NODE:
+    return(rb_str_new2("entity"));
+  case XML_PI_NODE:
+    return(rb_str_new2("pi"));
+  case XML_COMMENT_NODE:
+    return(rb_str_new2("comment"));
+  case XML_DOCUMENT_NODE:
+    return(rb_str_new2("document_xml"));
+  case XML_DOCUMENT_TYPE_NODE:
+    return(rb_str_new2("doctype"));
+  case XML_DOCUMENT_FRAG_NODE:
+    return(rb_str_new2("fragment"));
+  case XML_NOTATION_NODE:
+    return(rb_str_new2("notation"));
+  case XML_HTML_DOCUMENT_NODE:
+    return(rb_str_new2("document_html"));
+  case XML_DTD_NODE:
+    return(rb_str_new2("dtd"));
+  case XML_ELEMENT_DECL:
+    return(rb_str_new2("elem_decl"));
+  case XML_ATTRIBUTE_DECL:
+    return(rb_str_new2("attribute_decl"));
+  case XML_ENTITY_DECL:
+    return(rb_str_new2("entity_decl"));
+  case XML_NAMESPACE_DECL:
+    return(rb_str_new2("namespace"));
+  case XML_XINCLUDE_START:
+    return(rb_str_new2("xinclude_start"));
+  case XML_XINCLUDE_END:
+    return(rb_str_new2("xinclude_end"));
+#ifdef LIBXML_DOCB_ENABLED
+  case XML_DOCB_DOCUMENT_NODE:
+    return(rb_str_new2("document_docbook"));
+#endif
+  default:
+    rb_raise(eXMLNodeUnknownType, "Unknown node type: %n", rxn->node->type);
+    return(Qfalse);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    node.xinclude_end? => num
+ * 
+ * Determine whether this node is an xinclude end node.
+ */
+VALUE
+ruby_xml_node_xinclude_end_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_XINCLUDE_END)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    node.xinclude_start? => num
+ * 
+ * Determine whether this node is an xinclude start node.
+ */
+VALUE
+ruby_xml_node_xinclude_start_q(VALUE self) {
+  ruby_xml_node *rxn;
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+  if (rxn->node->type == XML_XINCLUDE_START)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+// TODO my gut tells me this is where our sigseg etc. problems start...      
+
+/*
+ * call-seq:
+ *    node.copy => node
+ * 
+ * Create a copy of this node.
+ */
+VALUE
+ruby_xml_node_copy(VALUE self, VALUE deep) {   /* MUFF */
+  ruby_xml_node *rxn, *n_rxn;
+  VALUE n_node;
+  
+  Data_Get_Struct(self, ruby_xml_node, rxn);
+
+  n_node = ruby_xml_node_new(cXMLNode, NULL); // class??
+  Data_Get_Struct(n_node, ruby_xml_node, n_rxn);
+
+  n_rxn->node = xmlCopyNode( rxn->node, ((deep==Qnil)||(deep==Qfalse))?0:1 );
+  if (rxn->node == NULL)
+    return(Qnil);
+
+  return n_node;
+}
+
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_node(void) {
+  cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
+  eXMLNodeSetNamespace = rb_define_class_under(cXMLNode, "SetNamespace", rb_eException);
+  eXMLNodeFailedModify = rb_define_class_under(cXMLNode, "FailedModify", rb_eException);
+  eXMLNodeUnknownType = rb_define_class_under(cXMLNode, "UnknownType", rb_eException);
+
+  rb_define_const(cXMLNode, "SPACE_DEFAULT", INT2NUM(0));
+  rb_define_const(cXMLNode, "SPACE_PRESERVE", INT2NUM(1));
+  rb_define_const(cXMLNode, "SPACE_NOT_INHERIT", INT2NUM(-1));
+  rb_define_const(cXMLNode, "XLINK_ACTUATE_AUTO", INT2NUM(1));
+  rb_define_const(cXMLNode, "XLINK_ACTUATE_NONE", INT2NUM(0));
+  rb_define_const(cXMLNode, "XLINK_ACTUATE_ONREQUEST", INT2NUM(2));
+  rb_define_const(cXMLNode, "XLINK_SHOW_EMBED", INT2NUM(2));
+  rb_define_const(cXMLNode, "XLINK_SHOW_NEW", INT2NUM(1));
+  rb_define_const(cXMLNode, "XLINK_SHOW_NONE", INT2NUM(0));
+  rb_define_const(cXMLNode, "XLINK_SHOW_REPLACE", INT2NUM(3));
+  rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED", INT2NUM(2));
+  rb_define_const(cXMLNode, "XLINK_TYPE_EXTENDED_SET", INT2NUM(3));
+  rb_define_const(cXMLNode, "XLINK_TYPE_NONE", INT2NUM(0));
+  rb_define_const(cXMLNode, "XLINK_TYPE_SIMPLE", INT2NUM(1));
+
+  rb_define_singleton_method(cXMLNode, "new", ruby_xml_node_initialize, -1);
+
+  rb_define_method(cXMLNode, "<<", ruby_xml_node_content_add, 1);
+  rb_define_method(cXMLNode, "[]", ruby_xml_node_property_get, 1);
+  rb_define_method(cXMLNode, "[]=", ruby_xml_node_property_set, 2);
+  rb_define_method(cXMLNode, "attribute?", ruby_xml_node_attribute_q, 0);
+  rb_define_method(cXMLNode, "attribute_decl?", ruby_xml_node_attribute_decl_q, 0);
+  rb_define_method(cXMLNode, "base", ruby_xml_node_base_get, 0);
+  rb_define_method(cXMLNode, "base=", ruby_xml_node_base_set, 1);
+  rb_define_method(cXMLNode, "blank?", ruby_xml_node_empty_q, 0);
+  rb_define_method(cXMLNode, "cdata?", ruby_xml_node_cdata_q, 0);
+  rb_define_method(cXMLNode, "comment?", ruby_xml_node_comment_q, 0);
+  rb_define_method(cXMLNode, "copy", ruby_xml_node_copy, 1);
+  rb_define_method(cXMLNode, "child", ruby_xml_node_child_get, 0);
+  rb_define_method(cXMLNode, "child?", ruby_xml_node_child_q, 0);
+  rb_define_method(cXMLNode, "child=", ruby_xml_node_child_set, 1);
+  rb_define_method(cXMLNode, "children", ruby_xml_node_child_get, 0);
+  rb_define_method(cXMLNode, "children?", ruby_xml_node_child_q, 0);
+  rb_define_method(cXMLNode, "content", ruby_xml_node_content_get, 0);
+  rb_define_method(cXMLNode, "content=", ruby_xml_node_content_set, 1);
+  rb_define_method(cXMLNode, "content_stripped", ruby_xml_node_content_stripped_get, 0);
+  rb_define_method(cXMLNode, "doc", ruby_xml_node_doc, 0);
+  rb_define_method(cXMLNode, "docbook_doc?", ruby_xml_node_docbook_doc_q, 0);
+  rb_define_method(cXMLNode, "doctype?", ruby_xml_node_doctype_q, 0);
+  rb_define_method(cXMLNode, "document?", ruby_xml_node_document_q, 0);
+  rb_define_method(cXMLNode, "dtd?", ruby_xml_node_dtd_q, 0);
+  rb_define_method(cXMLNode, "dump", ruby_xml_node_dump, 0);
+  rb_define_method(cXMLNode, "debug_dump", ruby_xml_node_debug_dump, 0);
+  rb_define_method(cXMLNode, "element?", ruby_xml_node_element_q, 0);
+  rb_define_method(cXMLNode, "element_decl?", ruby_xml_node_element_decl_q, 0);
+  rb_define_method(cXMLNode, "empty?", ruby_xml_node_empty_q, 0);
+  rb_define_method(cXMLNode, "entity?", ruby_xml_node_entity_q, 0);
+  rb_define_method(cXMLNode, "entity_ref?", ruby_xml_node_entity_ref_q, 0);
+  rb_define_method(cXMLNode, "eql?", ruby_xml_node_eql_q, 1);
+  rb_define_method(cXMLNode, "find", ruby_xml_node_find, -1);
+  rb_define_method(cXMLNode, "find_first", ruby_xml_node_find_first, -1);
+  rb_define_method(cXMLNode, "fragment?", ruby_xml_node_fragment_q, 0);
+  rb_define_method(cXMLNode, "hash", ruby_xml_node_hash, 0);
+  rb_define_method(cXMLNode, "html_doc?", ruby_xml_node_html_doc_q, 0);
+  rb_define_method(cXMLNode, "lang", ruby_xml_node_lang_get, 0);
+  rb_define_method(cXMLNode, "lang=", ruby_xml_node_lang_set, 1);
+  rb_define_method(cXMLNode, "last", ruby_xml_node_last_get, 0);
+  rb_define_method(cXMLNode, "last?", ruby_xml_node_last_q, 0);
+  rb_define_method(cXMLNode, "line_num", ruby_xml_node_line_num, 0);
+  rb_define_method(cXMLNode, "name", ruby_xml_node_name_get, 0);
+  rb_define_method(cXMLNode, "name=", ruby_xml_node_name_set, 1);
+  rb_define_method(cXMLNode, "namespace", ruby_xml_node_namespace_get, 0);
+  rb_define_method(cXMLNode, "namespace_node", ruby_xml_node_namespace_get_node, 0);
+  rb_define_method(cXMLNode, "namespace?", ruby_xml_node_namespace_q, 0);  
+  rb_define_method(cXMLNode, "namespace=", ruby_xml_node_namespace_set, -1);  
+  rb_define_method(cXMLNode, "next", ruby_xml_node_next_get, 0);
+  rb_define_method(cXMLNode, "next?", ruby_xml_node_next_q, 0);
+  rb_define_method(cXMLNode, "node_type", ruby_xml_node_type, 0);
+  rb_define_method(cXMLNode, "node_type_name", ruby_xml_node_type_name, 0);
+  rb_define_method(cXMLNode, "notation?", ruby_xml_node_notation_q, 0);
+  rb_define_method(cXMLNode, "ns", ruby_xml_node_namespace_get, 0);
+  rb_define_method(cXMLNode, "ns?", ruby_xml_node_ns_q, 0);
+  rb_define_method(cXMLNode, "ns_def", ruby_xml_node_ns_def_get, 0);
+  rb_define_method(cXMLNode, "ns_def?", ruby_xml_node_ns_def_q, 0);
+  rb_define_method(cXMLNode, "parent", ruby_xml_node_parent_get, 0);
+  rb_define_method(cXMLNode, "parent?", ruby_xml_node_parent_q, 0);
+  rb_define_method(cXMLNode, "path", ruby_xml_node_path, 0);
+  rb_define_method(cXMLNode, "pi?", ruby_xml_node_pi_q, 0);
+  rb_define_method(cXMLNode, "pointer", ruby_xml_node_pointer, 1);
+  rb_define_method(cXMLNode, "prev", ruby_xml_node_prev_get, 0);
+  rb_define_method(cXMLNode, "prev?", ruby_xml_node_prev_q, 0);
+  rb_define_method(cXMLNode, "property", ruby_xml_node_property_get, 1);
+  rb_define_method(cXMLNode, "properties", ruby_xml_node_properties_get, 0);
+  rb_define_method(cXMLNode, "properties?", ruby_xml_node_properties_q, 0);
+  rb_define_method(cXMLNode, "remove!", ruby_xml_node_remove_ex, 0);
+  rb_define_method(cXMLNode, "search_ns", ruby_xml_node_search_ns, 1);
+  rb_define_method(cXMLNode, "search_href", ruby_xml_node_search_href, 1);
+  rb_define_method(cXMLNode, "sibling=", ruby_xml_node_sibling_set, 1);
+  rb_define_method(cXMLNode, "space_preserve", ruby_xml_node_space_preserve_get, 0);
+  rb_define_method(cXMLNode, "space_preserve=", ruby_xml_node_space_preserve_set, 1);
+  rb_define_method(cXMLNode, "text?", ruby_xml_node_text_q, 0);
+  rb_define_method(cXMLNode, "to_s", ruby_xml_node_to_s, 0);
+  rb_define_method(cXMLNode, "xinclude_end?", ruby_xml_node_xinclude_end_q, 0);
+  rb_define_method(cXMLNode, "xinclude_start?", ruby_xml_node_xinclude_start_q, 0);
+  rb_define_method(cXMLNode, "xlink?", ruby_xml_node_xlink_q, 0);
+  rb_define_method(cXMLNode, "xlink_type", ruby_xml_node_xlink_type, 0);
+  rb_define_method(cXMLNode, "xlink_type_name", ruby_xml_node_xlink_type_name, 0);
+
+  rb_define_alias(cXMLNode, "==", "eql?");
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_node.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_node.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_node.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,28 @@
+/* $Id: ruby_xml_node.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_NODE__
+#define __RUBY_XML_NODE__
+
+extern VALUE cXMLNode;
+extern VALUE eXMLNodeSetNamespace;
+extern VALUE eXMLNodeFailedModify;
+extern VALUE eXMLNodeUnknownType;
+
+typedef struct ruby_xml_node {
+  xmlNodePtr node;
+  VALUE xd;
+  int is_ptr;
+} ruby_xml_node;
+
+void ruby_xml_node_free(ruby_xml_node *rxn);
+void ruby_init_xml_node(void);
+VALUE ruby_xml_node_child_set(VALUE self, VALUE obj);
+VALUE ruby_xml_node_new(VALUE class, xmlNodePtr node);
+VALUE ruby_xml_node_new2(VALUE class, VALUE xd, xmlNodePtr node);
+VALUE ruby_xml_node_name_get(VALUE self);
+VALUE ruby_xml_node_property_get(VALUE self, VALUE key);
+VALUE ruby_xml_node_property_set(VALUE self, VALUE key, VALUE val);
+VALUE ruby_xml_node_set_ptr(VALUE node, int is_ptr);
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_node_set.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_node_set.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_node_set.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,248 @@
+/* $Id: ruby_xml_node_set.c,v 1.3 2006/04/14 14:45:25 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_node_set.h"
+
+/*
+ * Document-class: XML::Node::Set
+ * 
+ * Includes Enumerable.
+ */
+VALUE cXMLNodeSet;
+
+// TODO maybe we should support [] on nodeset?
+//      Would also give us on xpath too...
+
+/*
+ * call-seq:
+ *    nodeset.to_a => [node, ..., node]
+ * 
+ * Obtain an array of the nodes in this set.
+ */
+VALUE
+ruby_xml_node_set_to_a(VALUE self) {
+  int i;
+  ruby_xml_node_set *rxnset;
+  VALUE nodeobj, set_ary;
+
+  Data_Get_Struct(self, ruby_xml_node_set, rxnset);
+
+  set_ary = rb_ary_new();
+  if (!((rxnset->node_set == NULL) || (rxnset->node_set->nodeNr == 0))) {
+    for (i = 0; i < rxnset->node_set->nodeNr; i++) {
+      nodeobj = ruby_xml_node_new2(cXMLNode, rxnset->xd, rxnset->node_set->nodeTab[i]);
+      rb_ary_push(set_ary, nodeobj);
+    }
+  }
+  
+  return(set_ary);
+}
+
+
+/*
+ * call-seq:
+ *    nodeset.each { |node| ... } => self
+ * 
+ * Call the supplied block for each node in this set.
+ */
+VALUE
+ruby_xml_node_set_each(VALUE self) {
+  int i;
+  ruby_xml_node_set *rxnset;
+  VALUE nodeobj;
+
+  Data_Get_Struct(self, ruby_xml_node_set, rxnset);
+
+  if (rxnset->node_set == NULL)
+    return(Qnil);
+
+  for (i = 0; i < rxnset->node_set->nodeNr; i++) {
+    switch(rxnset->node_set->nodeTab[i]->type) {
+    case XML_ATTRIBUTE_NODE:
+      nodeobj = ruby_xml_attr_new2(cXMLAttr, rxnset->xd, (xmlAttrPtr)rxnset->node_set->nodeTab[i]);
+      break;
+    default:
+      nodeobj = ruby_xml_node_new2(cXMLNode, rxnset->xd, rxnset->node_set->nodeTab[i]);
+    }
+
+    rb_yield(nodeobj);
+  }
+  return(self);
+}
+
+
+/*
+ * call-seq:
+ *    nodeset.empty? => (true|false)
+ *
+ * Determine whether this nodeset is empty (contains no nodes).
+ */
+VALUE
+ruby_xml_node_set_empty_q(VALUE self) {
+  ruby_xml_node_set *rxnset;
+    Data_Get_Struct(self, ruby_xml_node_set, rxnset);
+  return ( rxnset->node_set == NULL || rxnset->node_set->nodeNr <= 0 ) ? Qtrue : Qfalse;
+}
+
+
+/*
+ * call-seq:
+ *    nodeset.first => node
+ *
+ * Returns the first node in this node set, or nil if none exist.
+ */
+VALUE
+ruby_xml_node_set_first(VALUE self) {
+  ruby_xml_node_set *rxnset; 
+  VALUE nodeobj;
+
+  Data_Get_Struct(self, ruby_xml_node_set, rxnset);
+  
+  if (rxnset->node_set == NULL || rxnset->node_set->nodeNr < 1)
+    return(Qnil);
+    
+  switch(rxnset->node_set->nodeTab[0]->type) {
+    case XML_ATTRIBUTE_NODE:
+      nodeobj = ruby_xml_attr_new2(cXMLAttr, rxnset->xd, (xmlAttrPtr)rxnset->node_set->nodeTab[0]);
+      break;
+    default:
+      nodeobj = ruby_xml_node_new2(cXMLNode, rxnset->xd, rxnset->node_set->nodeTab[0]);
+  }
+
+  return(nodeobj);
+}
+
+
+void
+ruby_xml_node_set_free(ruby_xml_node_set *rxnset) {
+  void *data;
+
+  switch(rxnset->data_type) {
+  case RUBY_LIBXML_SRC_TYPE_NULL:
+    break;
+  case RUBY_LIBXML_SRC_TYPE_XPATH:
+    data = (void*)(rx_xpath_data *)rxnset->data;
+    free((rx_xpath_data *)data);
+  default:
+    rb_fatal("Unknown data type, %d", rxnset->data_type);
+  }
+
+  /* Don't need to free the node set because the nodeset is a child of
+     the XPath object that created the set.
+    if (rxnset->node_set != NULL)
+      xmlXPathFreeNodeSet(rxnset->node_set);
+  */
+
+  free(rxnset);
+}
+
+
+/*
+ * call-seq:
+ *    nodeset.length => num
+ * 
+ * Obtain the length of this nodeset.
+ */
+VALUE
+ruby_xml_node_set_length(VALUE self) {
+  ruby_xml_node_set *rxnset;
+  Data_Get_Struct(self, ruby_xml_node_set, rxnset);
+  if (rxnset->node_set == NULL)
+    return(Qnil);
+  else
+    return(INT2NUM(rxnset->node_set->nodeNr));
+}
+
+
+static void
+ruby_xml_node_set_mark(ruby_xml_node_set *rxnset) {
+  if (rxnset == NULL) return;
+  if (!NIL_P(rxnset->xd)) rb_gc_mark(rxnset->xd);
+  if (!NIL_P(rxnset->xpath)) rb_gc_mark(rxnset->xpath);
+}
+
+
+VALUE
+ruby_xml_node_set_new(VALUE class, VALUE xd, VALUE xpath,
+			    xmlNodeSetPtr node_set) {
+  ruby_xml_node_set *rxnset;
+
+  rxnset = ALLOC(ruby_xml_node_set);
+  rxnset->node_set = node_set;
+  rxnset->data = NULL;
+  rxnset->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
+  rxnset->xd = xd;
+  rxnset->xpath = xpath;
+  return(Data_Wrap_Struct(class, ruby_xml_node_set_mark,
+			  ruby_xml_node_set_free, rxnset));
+}
+
+
+VALUE
+ruby_xml_node_set_new2(VALUE xd, VALUE xpath,
+			     xmlNodeSetPtr node_set) {
+  return(ruby_xml_node_set_new(cXMLNodeSet, xd, xpath, node_set));
+}
+
+
+/*
+ * call-seq:
+ *    nodeset.xpath => xpath
+ * 
+ * Obtain the xpath corresponding to this nodeset, if any.
+ */
+VALUE
+ruby_xml_node_set_xpath_get(VALUE self) {
+  ruby_xml_node_set *rxnset;
+
+  Data_Get_Struct(self, ruby_xml_node_set, rxnset);
+  if (NIL_P(rxnset->xpath))
+    return(Qnil);
+  else
+    return(rxnset->xpath);
+}
+
+
+/*
+ * call-seq:
+ *    nodeset.xpath_ctxt => context
+ * 
+ * Return the xpath context corresponding to this nodeset,
+ * if any.
+ */
+VALUE
+ruby_xml_node_set_xpath_data_get(VALUE self) {
+  ruby_xml_node_set *rxnset;
+  rx_xpath_data *rxxpd;
+
+  Data_Get_Struct(self, ruby_xml_node_set, rxnset);
+  if (rxnset->data_type != RUBY_LIBXML_SRC_TYPE_XPATH)
+    return(Qnil);
+
+  rxxpd = (rx_xpath_data *)rxnset->data;
+  return(rxxpd->ctxt);
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+	mXML = rb_define_module("XML");
+  cXMLNode = rb_define_class_under(mXML, "Node", rb_cObject);
+#endif
+
+void
+ruby_init_xml_node_set(void) {
+  cXMLNodeSet = rb_define_class_under(cXMLNode, "Set", rb_cObject);  
+  rb_include_module(cXMLNodeSet, rb_const_get(rb_cObject, rb_intern("Enumerable")));
+
+  rb_define_method(cXMLNodeSet, "each", ruby_xml_node_set_each, 0);
+  rb_define_method(cXMLNodeSet, "empty?", ruby_xml_node_set_empty_q, 0);
+  rb_define_method(cXMLNodeSet, "first", ruby_xml_node_set_first, 0);
+  rb_define_method(cXMLNodeSet, "length", ruby_xml_node_set_length, 0);
+  rb_define_method(cXMLNodeSet, "to_a", ruby_xml_node_set_to_a, 0);
+  rb_define_method(cXMLNodeSet, "xpath", ruby_xml_node_set_xpath_get, 0);
+  rb_define_method(cXMLNodeSet, "xpath_ctxt",
+		   ruby_xml_node_set_xpath_data_get, 0);
+       
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_node_set.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_node_set.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_node_set.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,26 @@
+/* $Id: ruby_xml_node_set.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_NODE_SET__
+#define __RUBY_XML_NODE_SET__
+
+extern VALUE cXMLNodeSet;
+
+typedef struct ruby_xml_node_set {
+  xmlNodeSetPtr node_set;
+  VALUE xd;
+  VALUE xpath;
+  int data_type;
+  void *data;
+} ruby_xml_node_set;
+
+void ruby_xml_node_set_free(ruby_xml_node_set *rxnset);
+void ruby_init_xml_node_set(void);
+VALUE ruby_xml_node_set_new(VALUE class, VALUE xd, VALUE xpath,
+			    xmlNodeSetPtr node_set);
+VALUE ruby_xml_node_set_new2(VALUE xd, VALUE xpath,
+			     xmlNodeSetPtr node_set);
+VALUE ruby_xml_node_set_each(VALUE self);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_ns.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_ns.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_ns.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,153 @@
+/* $Id: ruby_xml_ns.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_ns.h"
+
+VALUE cXMLNS;
+
+/*
+ * call-seq:
+ *    ns.href => "href"
+ * 
+ * Obtain the namespace's href.
+ */
+VALUE
+ruby_xml_ns_href_get(VALUE self) {
+  ruby_xml_ns *rxns;
+  Data_Get_Struct(self, ruby_xml_ns, rxns);
+  if (rxns->ns == NULL || rxns->ns->href == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxns->ns->href));
+}
+
+
+/*
+ * call-seq:
+ *    ns.href? => (true|false)
+ * 
+ * Determine whether this namespace has an href.
+ */
+VALUE
+ruby_xml_ns_href_q(VALUE self) {
+  ruby_xml_ns *rxns;
+  Data_Get_Struct(self, ruby_xml_ns, rxns);
+  if (rxns->ns == NULL || rxns->ns->href == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+void
+ruby_xml_ns_free(ruby_xml_ns *rxns) {
+  if (rxns->ns != NULL && !rxns->is_ptr) {
+    xmlFreeNs(rxns->ns);
+    rxns->ns = NULL;
+  }
+
+  free(rxns);
+}
+
+
+static void
+ruby_xml_ns_mark(ruby_xml_ns *rxns) {
+  if (rxns == NULL) return;
+  if (!NIL_P(rxns->xd)) rb_gc_mark(rxns->xd);
+}
+
+
+VALUE
+ruby_xml_ns_new(VALUE class, VALUE xd, xmlNsPtr ns) {
+  ruby_xml_ns *rxns;
+
+  rxns = ALLOC(ruby_xml_ns);
+  rxns->is_ptr = 0;
+  rxns->ns = ns;
+  rxns->xd = xd;
+  return(Data_Wrap_Struct(class, ruby_xml_ns_mark,
+			  ruby_xml_ns_free, rxns));
+}
+
+
+VALUE
+ruby_xml_ns_new2(VALUE class, VALUE xd, xmlNsPtr ns) {
+  ruby_xml_ns *rxns;
+
+  rxns = ALLOC(ruby_xml_ns);
+  rxns->is_ptr = 1;
+  rxns->ns = ns;
+  rxns->xd = xd;
+  return(Data_Wrap_Struct(class, ruby_xml_ns_mark,
+			  ruby_xml_ns_free, rxns));
+}
+
+
+/*
+ * call-seq:
+ *    ns.next => ns
+ * 
+ * Obtain the next namespace.
+ */
+VALUE
+ruby_xml_ns_next(VALUE self) {
+  ruby_xml_ns *rxns;
+  Data_Get_Struct(self, ruby_xml_ns, rxns);
+  if (rxns->ns == NULL || rxns->ns->next == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_ns_new2(cXMLNS, rxns->xd, rxns->ns->next));
+}
+
+
+/*
+ * call-seq:
+ *    ns.prefix => "prefix"
+ *    ns.to_s   => "prefix"
+ * 
+ * Obtain the namespace's prefix.
+ */
+VALUE
+ruby_xml_ns_prefix_get(VALUE self) {
+  ruby_xml_ns *rxns;
+  Data_Get_Struct(self, ruby_xml_ns, rxns);
+  if (rxns->ns == NULL || rxns->ns->prefix == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxns->ns->prefix));
+}
+
+
+/*
+ * call-seq:
+ *    ns.prefix? => (true|false)
+ * 
+ * Determine whether this namespace has a prefix.
+ */
+VALUE
+ruby_xml_ns_prefix_q(VALUE self) {
+  ruby_xml_ns *rxns;
+  Data_Get_Struct(self, ruby_xml_ns, rxns);
+  if (rxns->ns == NULL || rxns->ns->prefix == NULL)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_ns(void) {
+  cXMLNS = rb_define_class_under(mXML, "NS", rb_cObject);
+  rb_define_method(cXMLNS, "href", ruby_xml_ns_href_get, 0);
+  rb_define_method(cXMLNS, "href?", ruby_xml_ns_href_q, 0);
+  rb_define_method(cXMLNS, "next", ruby_xml_ns_next, 0);
+  rb_define_method(cXMLNS, "prefix", ruby_xml_ns_prefix_get, 0);
+  rb_define_method(cXMLNS, "prefix?", ruby_xml_ns_prefix_q, 0);
+  rb_define_method(cXMLNS, "to_s", ruby_xml_ns_prefix_get, 0);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_ns.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_ns.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_ns.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,21 @@
+/* $Id: ruby_xml_ns.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_NS__
+#define __RUBY_XML_NS__
+
+extern VALUE cXMLNS;
+
+typedef struct ruby_xml_ns {
+  xmlNsPtr ns;
+  int is_ptr;
+  VALUE xd;
+} ruby_xml_ns;
+
+void ruby_xml_ns_free(ruby_xml_ns *rxn);
+void ruby_init_xml_ns(void);
+VALUE ruby_xml_ns_new(VALUE class, VALUE xd, xmlNsPtr ns);
+VALUE ruby_xml_ns_new2(VALUE class, VALUE xd, xmlNsPtr ns);
+VALUE ruby_xml_ns_name_get(VALUE self);
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_parser.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_parser.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_parser.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,1417 @@
+/* $Id: ruby_xml_parser.c,v 1.3 2006/03/27 20:49:19 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+
+static VALUE libxml_xmlRubyErrorProc = Qnil;
+static int id_call;
+
+int ruby_xml_parser_count = 0;
+VALUE cXMLParser;
+VALUE eXMLParserParseError;
+
+static int
+ctxtRead(FILE *f, char * buf, int len) {
+    return(fread(buf, 1, len, f));
+}
+
+/*
+ * call-seq:
+ * 		XML::Parser.catalog_dump => true
+ * 
+ * Dump the parser resource catalogs to stdout.
+ */
+VALUE
+ruby_xml_parser_catalog_dump(VALUE self) {
+  xmlCatalogDump(stdout);
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.catalog_remove(catalog) => true
+ * 
+ * Remove the specified resource catalog.
+ */
+VALUE
+ruby_xml_parser_catalog_remove(VALUE self, VALUE cat) {
+  Check_Type(cat, T_STRING);
+  xmlCatalogRemove((xmlChar *)StringValuePtr(cat));
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.check_lib_versions => true							
+ * 
+ * Check LIBXML version matches version the bindings
+ * were compiled to. Throws an exception if not.
+ */
+VALUE
+ruby_xml_parser_check_lib_versions(VALUE class) {
+  xmlCheckVersion(LIBXML_VERSION);
+  return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_automata? => (true|false)
+ * 
+ * Determine whether libxml regexp automata support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_automata_q(VALUE class) {
+#ifdef LIBXML_AUTOMATA_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_c14n? => (true|false)
+ * 
+ * Determine whether libxml 'canonical XML' support is enabled.
+ * See "Canonical XML" (http://www.w3.org/TR/xml-c14n)
+ */
+VALUE
+ruby_xml_parser_enabled_c14n_q(VALUE class) {
+#ifdef LIBXML_C14N_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_catalog? => (true|false)                                         
+ * 
+ * Determine whether libxml resource catalog support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_catalog_q(VALUE class) {
+#ifdef LIBXML_CATALOG_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_debug? => (true|false)  
+ * 
+ * Determine whether libxml debugging support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_debug_q(VALUE class) {
+#ifdef LIBXML_DEBUG_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_docbook? => (true|false)  
+ * 
+ * Determine whether libxml docbook support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_docbook_q(VALUE class) {
+#ifdef LIBXML_DOCB_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_ftp? => (true|false)  
+ * 
+ * Determine whether libxml ftp client support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_ftp_q(VALUE class) {
+#ifdef LIBXML_FTP_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_http? => (true|false)  
+ * 
+ * Determine whether libxml http client support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_http_q(VALUE class) {
+#ifdef LIBXML_HTTP_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_html? => (true|false)  
+ * 
+ * Determine whether libxml html support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_html_q(VALUE class) {
+#ifdef LIBXML_HTML_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_iconv? => (true|false)  
+ * 
+ * Determine whether libxml iconv support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_iconv_q(VALUE class) {
+#ifdef LIBXML_ICONV_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_memory_debug? => (true|false)  
+ * 
+ * Determine whether libxml memory location debugging support
+ * is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_memory_debug_location_q(VALUE class) {
+#ifdef DEBUG_MEMORY_LOCATION
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_regexp? => (true|false)  
+ * 
+ * Determine whether libxml regular expression support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_regexp_q(VALUE class) {
+#ifdef LIBXML_REGEXP_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_schemas? => (true|false)  
+ * 
+ * Determine whether libxml schema support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_schemas_q(VALUE class) {
+#ifdef LIBXML_SCHEMAS_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_thread? => (true|false)  
+ * 
+ * Determine whether libxml thread-safe semantics support 
+ * is enabled (I think?).
+ */
+VALUE
+ruby_xml_parser_enabled_thread_q(VALUE class) {
+#ifdef LIBXML_THREAD_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_unicode? => (true|false)  
+ * 
+ * Determine whether libxml unicode support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_unicode_q(VALUE class) {
+#ifdef LIBXML_UNICODE_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_xinclude? => (true|false)  
+ * 
+ * Determine whether libxml xinclude support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_xinclude_q(VALUE class) {
+#ifdef LIBXML_XINCLUDE_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_xpath? => (true|false)  
+ * 
+ * Determine whether libxml xpath support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_xpath_q(VALUE class) {
+#ifdef LIBXML_XPATH_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_xpointer? => (true|false)  
+ * 
+ * Determine whether libxml xpointer support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_xpointer_q(VALUE class) {
+#ifdef LIBXML_XPTR_ENABLED
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ * 		XML::Parser.enabled_zlib? => (true|false)  
+ * 
+ * Determine whether libxml zlib support is enabled.
+ */
+VALUE
+ruby_xml_parser_enabled_zlib_q(VALUE class) {
+#ifdef HAVE_ZLIB_H
+  return(Qtrue);
+#else
+ return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.debug_entities => (true|false)
+ * 
+ * Determine whether included-entity debugging is enabled.
+ * (Requires Libxml to be compiled with debugging support)
+ */
+VALUE
+ruby_xml_parser_debug_entities_get(VALUE class) {
+#ifdef LIBXML_DEBUG_ENABLED
+  if (xmlParserDebugEntities)
+    return(Qtrue);
+  else
+    return(Qfalse);
+#else
+  rb_warn("libxml was compiled with debugging turned off");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.debug_entities = true|false
+ * 
+ * Enable or disable included-entity debugging.
+ * (Requires Libxml to be compiled with debugging support)
+ */
+VALUE
+ruby_xml_parser_debug_entities_set(VALUE class, VALUE bool) {
+#ifdef LIBXML_DEBUG_ENABLED
+  if (TYPE(bool) == T_FALSE) {
+    xmlParserDebugEntities = 0;
+    return(Qfalse);
+  } else {
+    xmlParserDebugEntities = 1;
+    return(Qtrue);
+  }
+#else
+  rb_warn("libxml was compiled with debugging turned off");
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_keep_blanks => (true|false)
+ * 
+ * Determine whether parsers retain whitespace by default.
+ */
+VALUE
+ruby_xml_parser_default_keep_blanks_get(VALUE class) {
+  if (xmlKeepBlanksDefaultValue)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_keep_blanks = true|false
+ * 
+ * Controls whether parsers retain whitespace by default.
+ */
+VALUE
+ruby_xml_parser_default_keep_blanks_set(VALUE class, VALUE bool) {
+  if (TYPE(bool) == T_FALSE) {
+    xmlKeepBlanksDefaultValue = 0;
+    return(Qfalse);
+  } else if (TYPE(bool) == T_TRUE) {
+    xmlKeepBlanksDefaultValue = 1;
+    return(Qtrue);
+  } else {
+    rb_raise(rb_eArgError, "invalid argument, must be a boolean");
+  }
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_load_external_dtd => (true|false)
+ * 
+ * Determine whether parsers load external DTDs by default.
+ */
+VALUE
+ruby_xml_parser_default_load_external_dtd_get(VALUE class) {
+  if (xmlSubstituteEntitiesDefaultValue)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_load_external_dtd = true|false
+ * 
+ * Controls whether parsers load external DTDs by default.
+ */
+VALUE
+ruby_xml_parser_default_load_external_dtd_set(VALUE class, VALUE bool) {
+  if (TYPE(bool) == T_FALSE) {
+    xmlLoadExtDtdDefaultValue = 0;
+    return(Qfalse);
+  } else {
+    xmlLoadExtDtdDefaultValue = 1;
+    return(Qtrue);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_line_numbers => (true|false)
+ * 
+ * Determine whether parsers retain line-numbers by default.
+ */
+VALUE
+ruby_xml_parser_default_line_numbers_get(VALUE class) {
+  if (xmlLineNumbersDefaultValue)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_line_numbers = true|false
+ * 
+ * Controls whether parsers retain line-numbers by default.
+ */
+VALUE
+ruby_xml_parser_default_line_numbers_set(VALUE class, VALUE bool) {
+  if (TYPE(bool) == T_FALSE) {
+    xmlLineNumbersDefault(0);
+    return(Qfalse);
+  } else {
+    xmlLineNumbersDefault(1);
+    return(Qtrue);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_pedantic_parser => (true|false)
+ * 
+ * Determine whether parsers are pedantic by default.
+ */
+VALUE
+ruby_xml_parser_default_pedantic_parser_get(VALUE class) {
+  if (xmlPedanticParserDefaultValue)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_pedantic_parser = true|false
+ * 
+ * Controls whether parsers are pedantic by default.
+ */
+VALUE
+ruby_xml_parser_default_pedantic_parser_set(VALUE class, VALUE bool) {
+  if (TYPE(bool) == T_FALSE) {
+    xmlPedanticParserDefault(0);
+    return(Qfalse);
+  } else {
+    xmlPedanticParserDefault(1);
+    return(Qtrue);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_substitute_entities => (true|false)
+ * 
+ * Determine whether parsers perform inline entity substitution
+ * (for external entities) by default.
+ */
+VALUE
+ruby_xml_parser_default_substitute_entities_get(VALUE class) {
+  if (xmlSubstituteEntitiesDefaultValue)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_substitute_entities = true|false
+ * 
+ * Controls whether parsers perform inline entity substitution
+ * (for external entities) by default.
+ */
+VALUE
+ruby_xml_parser_default_substitute_entities_set(VALUE class, VALUE bool) {
+  if (TYPE(bool) == T_FALSE) {
+    xmlSubstituteEntitiesDefault(0);
+    return(Qfalse);
+  } else {
+    xmlSubstituteEntitiesDefault(1);
+    return(Qtrue);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_tree_indent_string => "string"
+ * 
+ * Obtain the default string used by parsers to indent the XML tree
+ * for output.
+ */
+VALUE
+ruby_xml_parser_default_tree_indent_string_get(VALUE class) {
+  if (xmlTreeIndentString == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2(xmlTreeIndentString));
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_tree_indent_string = "string"
+ * 
+ * Set the default string used by parsers to indent the XML tree
+ * for output.
+ */
+VALUE
+ruby_xml_parser_default_tree_indent_string_set(VALUE class, VALUE string) {
+  Check_Type(string, T_STRING);
+  xmlTreeIndentString = ruby_strdup(StringValuePtr(string));
+  return(string);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_validity_checking => (true|false)
+ * 
+ * Determine whether parsers perform XML validation by default.
+ */
+VALUE
+ruby_xml_parser_default_validity_checking_get(VALUE class) {
+  if (xmlDoValidityCheckingDefaultValue)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_validity_checking = true|false
+ * 
+ * Controls whether parsers perform XML validation by default.
+ */
+VALUE
+ruby_xml_parser_default_validity_checking_set(VALUE class, VALUE bool) {
+  if (TYPE(bool) == T_FALSE) {
+    xmlDoValidityCheckingDefaultValue = 0;
+    return(Qfalse);
+  } else {
+    xmlDoValidityCheckingDefaultValue = 1;
+    return(Qtrue);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_warnings => (true|false)
+ * 
+ * Determine whether parsers output warnings by default.
+ */
+VALUE
+ruby_xml_parser_default_warnings_get(VALUE class) {
+  if (xmlGetWarningsDefaultValue)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_warnings = true|false
+ * 
+ * Controls whether parsers output warnings by default.
+ */
+VALUE
+ruby_xml_parser_default_warnings_set(VALUE class, VALUE bool) {
+  if (TYPE(bool) == T_FALSE) {
+    xmlGetWarningsDefaultValue = 0;
+    return(Qfalse);
+  } else {
+    xmlGetWarningsDefaultValue = 1;
+    return(Qtrue);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_compression => (true|false)
+ * 
+ * Determine whether parsers use Zlib compression by default
+ * (requires libxml to be compiled with Zlib support).
+ */
+VALUE
+ruby_xml_parser_default_compression_get(VALUE class) {
+#ifdef HAVE_ZLIB_H
+  return(INT2FIX(xmlGetCompressMode()));
+#else
+  rb_warn("libxml was compiled without zlib support");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.default_compression = true|false
+ * 
+ * Controls whether parsers use Zlib compression by default
+ * (requires libxml to be compiled with Zlib support).
+ */
+VALUE
+ruby_xml_parser_default_compression_set(VALUE class, VALUE num) {
+#ifdef HAVE_ZLIB_H
+  Check_Type(num, T_FIXNUM);
+  xmlSetCompressMode(FIX2INT(num));
+  return(num);
+#else
+  rb_warn("libxml was compiled without zlib support");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.features => ["feature", ..., "feature"]
+ * 
+ * Obtains an array of strings representing features supported 
+ * (and enabled) by the installed libxml.
+ */
+VALUE
+ruby_xml_parser_features(VALUE class) {
+  VALUE arr, str;
+  int i, len = MAX_LIBXML_FEATURES_LEN;
+  char **list = NULL;
+
+  list = ALLOC_N(char *,MAX_LIBXML_FEATURES_LEN);
+  MEMZERO(list, char *, MAX_LIBXML_FEATURES_LEN);
+
+  arr = rb_ary_new();
+  if (xmlGetFeaturesList(&len, (const char **)list) == -1)
+    return Qnil;
+
+  for (i = 0; i < len; i++) {
+    str = rb_str_new2((const char *)list[i]);
+    rb_gc_unregister_address(&str);
+    rb_ary_push(arr, str);
+  }
+
+  if (len == MAX_LIBXML_FEATURES_LEN)
+    rb_warn("Please contact libxml-devel at rubyforge.org and ask to have the \"MAX_LIBXML_FEATURES_LEN increased\" because you could possibly be seeing an incomplete list");
+
+  ruby_xfree(list);
+  return(arr);
+}
+
+
+/*
+ * call-seq:
+ *    parser.filename => "filename"
+ * 
+ * Obtain the filename this parser will read from.
+ */
+VALUE
+ruby_xml_parser_filename_get(VALUE self) {
+  ruby_xml_parser *rxp;
+  rx_file_data *data;
+
+  Data_Get_Struct(self, ruby_xml_parser, rxp);
+  if (rxp->data == NULL)
+    return(Qnil);
+
+  if (rxp->data_type != RUBY_LIBXML_SRC_TYPE_FILE)
+    return(Qnil);
+
+  data = (rx_file_data *)rxp->data;
+  return(data->filename);
+}
+
+
+/*
+ * call-seq:
+ *    parser.filename = "filename"
+ * 
+ * Set the filename this parser will read from.
+ */
+VALUE
+ruby_xml_parser_filename_set(VALUE self, VALUE filename) {
+  ruby_xml_parser *rxp;
+  ruby_xml_parser_context *rxpc;
+  rx_file_data *data;
+
+  Check_Type(filename, T_STRING);
+  Data_Get_Struct(self, ruby_xml_parser, rxp);
+
+  if (rxp->data_type == RUBY_LIBXML_SRC_TYPE_NULL) {
+    if (rxp->data != NULL)
+      rb_fatal("crap, this should be null");
+
+    rxp->data_type = RUBY_LIBXML_SRC_TYPE_FILE;
+    data = ALLOC(rx_file_data);
+    rxp->data = data;
+  } else if (rxp->data_type != RUBY_LIBXML_SRC_TYPE_FILE) {
+    return(Qnil);
+  }
+
+  rxp->ctxt = ruby_xml_parser_context_new3();
+  data = (rx_file_data *)rxp->data;
+  data->filename = filename;
+
+  Data_Get_Struct(rxp->ctxt, ruby_xml_parser_context, rxpc);
+  rxpc->ctxt = xmlCreateFileParserCtxt(StringValuePtr(filename));
+  if (rxpc->ctxt == NULL)
+    rb_sys_fail(StringValuePtr(filename));
+
+  return(data->filename);
+}
+
+
+void
+ruby_xml_parser_free(ruby_xml_parser *rxp) {
+  void *data;
+
+  ruby_xml_parser_count--;
+  if (ruby_xml_parser_count == 0)
+    xmlCleanupParser();
+
+  switch(rxp->data_type) {
+  case RUBY_LIBXML_SRC_TYPE_NULL:
+    break;
+  case RUBY_LIBXML_SRC_TYPE_FILE:
+    data = (void *)(rx_file_data *)rxp->data;
+    free((rx_file_data *)data);
+    break;
+  case RUBY_LIBXML_SRC_TYPE_STRING:
+    data = (void *)(rx_string_data *)rxp->data;
+    free((rx_string_data *)data);
+    break;
+  case RUBY_LIBXML_SRC_TYPE_IO:
+    data = (void *)(rx_io_data *)rxp->data;
+    free((rx_io_data *)data);
+    break;
+  default:
+    rb_fatal("Unknown data type, %d", rxp->data_type);
+  }
+
+  free(rxp);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.indent_tree_output => (true|false)
+ * 
+ * Determines whether XML output will be indented 
+ * (using the string supplied to +default_indent_tree_string+)
+ */
+VALUE
+ruby_xml_parser_indent_tree_output_get(VALUE class) {
+  if (xmlIndentTreeOutput)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.indent_tree_output = true|false
+ * 
+ * Controls whether XML output will be indented 
+ * (using the string supplied to +default_indent_tree_string+)
+ */
+VALUE
+ruby_xml_parser_indent_tree_output_set(VALUE class, VALUE bool) {
+  if (TYPE(bool) == T_TRUE) {
+    xmlIndentTreeOutput = 1;
+    return(Qtrue);
+  } else if (TYPE(bool) == T_FALSE) {
+    xmlIndentTreeOutput = 0;
+    return(Qfalse);
+  } else {
+    rb_raise(rb_eArgError, "invalid argument, must be boolean");
+  }
+}
+
+
+/*
+ * call-seq:
+ *    parser.io => IO
+ * 
+ * Obtain the IO instance this parser works with.
+ */
+VALUE
+ruby_xml_parser_io_get(VALUE self, VALUE io) {
+  ruby_xml_parser *rxp;
+  rx_io_data *data;
+
+  Data_Get_Struct(self, ruby_xml_parser, rxp);
+
+  if (rxp->data_type == RUBY_LIBXML_SRC_TYPE_NULL ||
+      rxp->data_type != RUBY_LIBXML_SRC_TYPE_IO ||
+      rxp->data == NULL)
+    return(Qnil);
+
+  data = (rx_io_data *)rxp->data;
+
+  return(data->io);
+}
+
+
+/*
+ * call-seq:
+ *    parser.io = IO
+ * 
+ * Set the IO instance this parser works with.
+ */
+VALUE
+ruby_xml_parser_io_set(VALUE self, VALUE io) {
+  ruby_xml_parser *rxp;
+  ruby_xml_parser_context *rxpc;
+  rx_io_data *data;
+  OpenFile *fptr;
+  FILE *f;
+
+  if (!rb_obj_is_kind_of(io, rb_cIO))
+    rb_raise(rb_eTypeError, "need an IO object");
+
+  Data_Get_Struct(self, ruby_xml_parser, rxp);
+
+  if (rxp->data_type == RUBY_LIBXML_SRC_TYPE_NULL) {
+    if (rxp->data != NULL)
+      rb_fatal("crap, this should be null");
+
+    rxp->data_type = RUBY_LIBXML_SRC_TYPE_IO;
+    data = ALLOC(rx_io_data);
+    rxp->data = data;
+  } else if (rxp->data_type != RUBY_LIBXML_SRC_TYPE_IO) {
+    return(Qnil);
+  }
+
+  rxp->ctxt = ruby_xml_parser_context_new3();
+  data = (rx_io_data *)rxp->data;
+  data->io = io;
+
+  GetOpenFile(io, fptr);
+  rb_io_check_readable(fptr);
+  f = GetWriteFile(fptr);
+
+  Data_Get_Struct(rxp->ctxt, ruby_xml_parser_context, rxpc);
+  rxpc->ctxt = xmlCreateIOParserCtxt(NULL, NULL,
+				     (xmlInputReadCallback) ctxtRead,
+				     NULL, f, XML_CHAR_ENCODING_NONE);
+  if (NIL_P(rxpc->ctxt))
+    rb_sys_fail(0);
+
+  return(data->io);
+}
+
+
+void
+ruby_xml_parser_mark(ruby_xml_parser *rxp) {
+  if (rxp == NULL) return;
+  if (!NIL_P(rxp->ctxt)) rb_gc_mark(rxp->ctxt);
+
+  switch(rxp->data_type) {
+  case RUBY_LIBXML_SRC_TYPE_NULL:
+    break;
+  case RUBY_LIBXML_SRC_TYPE_FILE:
+    if (!NIL_P(((rx_file_data *)rxp->data)->filename))
+      rb_gc_mark(((rx_file_data *)rxp->data)->filename);
+    break;
+  case RUBY_LIBXML_SRC_TYPE_STRING:
+    if (!NIL_P(((rx_string_data *)rxp->data)->str))
+      rb_gc_mark(((rx_string_data *)rxp->data)->str);
+    break;
+  case RUBY_LIBXML_SRC_TYPE_IO:
+    if (!NIL_P(((rx_io_data *)rxp->data)->io))
+      rb_gc_mark(((rx_io_data *)rxp->data)->io);
+    break;
+  default:
+    rb_fatal("unknown datatype: %d", rxp->data_type);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.memory_dump => (true|false)
+ * 
+ * Perform a parser memory dump (requires memory debugging 
+ * support in libxml).
+ */
+VALUE
+ruby_xml_parser_memory_dump(VALUE self) {
+#ifdef DEBUG_MEMORY_LOCATION
+  xmlMemoryDump();
+  return(Qtrue);
+#else
+  rb_warn("libxml was compiled without memory debugging support");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.memory_used => num_bytes
+ * 
+ * Perform a parser memory dump (requires memory debugging 
+ * support in libxml).
+ */
+VALUE
+ruby_xml_parser_memory_used(VALUE self) {
+#ifdef DEBUG_MEMORY_LOCATION
+  return(INT2NUM(xmlMemUsed()));
+#else
+  rb_warn("libxml was compiled without memory debugging support");
+  return(Qfalse);
+#endif
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.new => parser
+ * 
+ * Create a new parser instance with no pre-determined source.
+ */
+VALUE
+ruby_xml_parser_new(VALUE class) {
+  ruby_xml_parser *rxp;
+
+  ruby_xml_parser_count++;
+  rxp = ALLOC(ruby_xml_parser);
+  rxp->ctxt = Qnil;
+  rxp->data_type = RUBY_LIBXML_SRC_TYPE_NULL;
+  rxp->data = NULL;
+  rxp->parsed = 0;
+
+  return(Data_Wrap_Struct(class, ruby_xml_parser_mark,
+			  ruby_xml_parser_free, rxp));
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.file => parser
+ * 
+ * Create a new parser instance that will read the specified file.
+ */
+VALUE
+ruby_xml_parser_new_file(VALUE class, VALUE filename) {
+  VALUE obj;
+  ruby_xml_parser *rxp;
+  rx_file_data *data;
+
+  obj = ruby_xml_parser_new(class);
+  Data_Get_Struct(obj, ruby_xml_parser, rxp);
+
+  data = ALLOC(rx_file_data);
+  rxp->data_type = RUBY_LIBXML_SRC_TYPE_FILE;
+  rxp->data = data;
+
+  ruby_xml_parser_filename_set(obj, filename);
+
+  return(obj);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.io => parser
+ * 
+ * Create a new parser instance that will read from the
+ * specified IO object.
+ */
+VALUE
+ruby_xml_parser_new_io(VALUE class, VALUE io) {
+  VALUE obj;
+  ruby_xml_parser *rxp;
+  rx_io_data *data;
+
+  obj = ruby_xml_parser_new(class);
+  Data_Get_Struct(obj, ruby_xml_parser, rxp);
+
+  data = ALLOC(rx_io_data);
+  rxp->data_type = RUBY_LIBXML_SRC_TYPE_IO;
+  rxp->data = data;
+
+  ruby_xml_parser_io_set(obj, io);
+
+  return(obj);
+}
+
+
+/*
+ * call-seq:
+ *    XML::Parser.string => parser
+ * 
+ * Create a new parser instance that will parse the given
+ * string.
+ */
+VALUE
+ruby_xml_parser_new_string(VALUE class, VALUE str) {
+  VALUE obj;
+  ruby_xml_parser *rxp;
+  rx_string_data *data;
+
+  obj = ruby_xml_parser_new(class);
+  Data_Get_Struct(obj, ruby_xml_parser, rxp);
+
+  data = ALLOC(rx_string_data);
+  rxp->data_type = RUBY_LIBXML_SRC_TYPE_STRING;
+  rxp->data = data;
+
+  ruby_xml_parser_str_set(obj, str);
+
+  return(obj);
+}
+
+
+/*
+ * call-seq:
+ *    parser.parse => document
+ * 
+ * Parse the input XML and create an XML::Document with
+ * it's content. If an error occurs, XML::Parser::ParseError
+ * is thrown.
+ */
+VALUE
+ruby_xml_parser_parse(VALUE self) {
+  ruby_xml_document *rxd;
+  ruby_xml_parser *rxp;
+  ruby_xml_parser_context *rxpc;
+  xmlDocPtr xdp;
+  VALUE doc;
+
+  Data_Get_Struct(self, ruby_xml_parser, rxp);
+
+  switch (rxp->data_type) {
+  case RUBY_LIBXML_SRC_TYPE_NULL:
+    return(Qnil);
+  case RUBY_LIBXML_SRC_TYPE_STRING:
+  case RUBY_LIBXML_SRC_TYPE_FILE:
+  case RUBY_LIBXML_SRC_TYPE_IO:
+    Data_Get_Struct(rxp->ctxt, ruby_xml_parser_context, rxpc);
+    if (xmlParseDocument(rxpc->ctxt) == -1) {
+      xmlFreeDoc(rxpc->ctxt->myDoc);
+      rb_raise(eXMLParserParseError, "Document didn't parse");
+    }
+
+    xdp = rxpc->ctxt->myDoc;
+    if (!rxpc->ctxt->wellFormed) {
+      xmlFreeDoc(xdp);
+      xdp = NULL;
+      rb_raise(eXMLParserParseError, "Document did not contain well-formed XML");
+    } else {
+      rxp->parsed = 1;
+    }
+
+    doc = ruby_xml_document_new(cXMLDocument, xdp);
+    Data_Get_Struct(doc, ruby_xml_document, rxd);
+    rxd->is_ptr = 0;
+    rxd->doc = xdp;
+    break;
+  default:
+    rb_fatal("Unknown data type, %d", rxp->data_type);
+  }
+
+  return(doc);
+}
+
+
+/*
+ * call-seq:
+ *    parser.context => context
+ * 
+ * Obtain the XML::Parser::Context associated with this
+ * parser.
+ */
+VALUE
+ruby_xml_parser_parser_context_get(VALUE self) {
+  ruby_xml_parser *rxp;
+
+  Data_Get_Struct(self, ruby_xml_parser, rxp);
+  if (rxp->ctxt == Qnil)
+    return(Qnil);
+  else
+    return(rxp->ctxt);
+}
+
+
+/*
+ * call-seq:
+ *    parser.string => "string"
+ * 
+ * Obtain the string this parser works with.
+ */
+VALUE
+ruby_xml_parser_str_get(VALUE self) {
+  ruby_xml_parser *rxp;
+  rx_string_data *data;
+
+  Data_Get_Struct(self, ruby_xml_parser, rxp);
+  if (rxp->data == NULL || rxp->data_type != RUBY_LIBXML_SRC_TYPE_STRING)
+    return(Qnil);
+
+  data = (rx_string_data *)rxp->data;
+  return(data->str);
+}
+
+
+/*
+ * call-seq:
+ *    parser.string = "string"
+ * 
+ * Set the string this parser works with.
+ */
+VALUE
+ruby_xml_parser_str_set(VALUE self, VALUE str) {
+  ruby_xml_parser *rxp;
+  ruby_xml_parser_context *rxpc;
+  rx_string_data *data;
+
+  Check_Type(str, T_STRING);
+  Data_Get_Struct(self, ruby_xml_parser, rxp);
+
+  if (rxp->data_type == RUBY_LIBXML_SRC_TYPE_NULL) {
+    rxp->data_type = RUBY_LIBXML_SRC_TYPE_STRING;
+    data = ALLOC(rx_string_data);
+    rxp->data = data;
+  } else if (rxp->data_type != RUBY_LIBXML_SRC_TYPE_STRING) {
+    return(Qnil);
+  }
+
+  rxp->ctxt = ruby_xml_parser_context_new3();
+  data = (rx_string_data *)rxp->data;
+  data->str = str;
+
+  Data_Get_Struct(rxp->ctxt, ruby_xml_parser_context, rxpc);
+  rxpc->ctxt = xmlCreateMemoryParserCtxt(StringValuePtr(data->str), RSTRING(data->str)->len);
+
+  return(data->str);
+}
+
+/*
+ * call-seq:
+ *    XML::Parser.register_error_handler(lambda { |msg| ... }) => old_handler
+ *    XML::Parser.register_error_handler(nil) => old_handler
+ * 
+ * Register the attached block as the handler for parser errors.
+ * A message describing parse errors is passed to the block.
+ * Libxml passes error messages to the handler in parts, one per call.
+ * A typical error results in six calls to this proc, with arguments:
+ * 
+ *   "Entity: line 1: ", 
+ *   "parser ", 
+ *   "error : ", 
+ *   "Opening and ending tag mismatch: foo line 1 and foz\n",
+ *   "<foo><bar/></foz>\n",
+ *   "                 ^\n"
+ * 
+ * Note that the error handler is shared by all threads.
+ */
+VALUE
+ruby_xml_parser_registerErrorHandler(VALUE self, VALUE proc) {
+  VALUE old_block = libxml_xmlRubyErrorProc;
+  libxml_xmlRubyErrorProc = proc;
+  return(old_block);
+}
+
+static void
+libxml_xmlErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, const char *msg, ...)
+{
+  va_list ap;
+  char str[1000];
+  VALUE rstr;
+
+  if (libxml_xmlRubyErrorProc == Qnil) {
+    va_start(ap, msg);
+    vfprintf(stderr, msg, ap);
+    va_end(ap);
+  } else {
+    va_start(ap, msg);
+    if (vsnprintf(str, 999, msg, ap) >= 998) str[999] = 0;
+    va_end(ap);
+
+    rstr = rb_str_new2(str);
+    rb_funcall2(libxml_xmlRubyErrorProc, id_call, 1, &rstr);
+  }
+}
+
+/* #define RUBY_XML_PARSER_ENABLED_INIT(func, method) \
+ rb_define_singleton_method(cXMLParser, method, \
+			   ruby_xml_parser_enabled_##func##_q, 0); */
+
+///#include "cbg.c"
+///
+///VALUE ruby_register_deb(VALUE self) {
+///  deb_register_cbg();
+///  return(Qtrue);
+///}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_parser(void) {
+	
+  cXMLParser = rb_define_class_under(mXML, "Parser", rb_cObject);
+  eXMLParserParseError = rb_define_class_under(cXMLParser, "ParseError",
+					       rb_eRuntimeError);
+
+  /* Constants */
+  rb_define_const(cXMLParser, "LIBXML_VERSION",
+		  rb_str_new2(LIBXML_DOTTED_VERSION));
+  rb_define_const(cXMLParser, "VERSION", rb_str_new2(RUBY_LIBXML_VERSION));
+  rb_define_const(cXMLParser, "VERNUM", INT2NUM(RUBY_LIBXML_VERNUM));
+
+  /* Question-esqe Class Methods */
+  /* RDoc won't have them defined by a macro... */
+  rb_define_singleton_method(cXMLParser, "enabled_automata?",
+			     ruby_xml_parser_enabled_automata_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_c14n?",
+			     ruby_xml_parser_enabled_c14n_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_catalog?",
+			     ruby_xml_parser_enabled_catalog_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_debug?",
+			     ruby_xml_parser_enabled_debug_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_docbook?",
+			     ruby_xml_parser_enabled_docbook_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_ftp?",
+			     ruby_xml_parser_enabled_ftp_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_http?",
+			     ruby_xml_parser_enabled_http_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_html?",
+			     ruby_xml_parser_enabled_html_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_iconv?",
+			     ruby_xml_parser_enabled_iconv_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_memory_debug?",
+			     ruby_xml_parser_enabled_memory_debug_location_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_regexp?",
+			     ruby_xml_parser_enabled_regexp_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_schemas?",
+			     ruby_xml_parser_enabled_schemas_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_thread?",
+			     ruby_xml_parser_enabled_thread_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_unicode?",
+			     ruby_xml_parser_enabled_unicode_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_xinclude?",
+			     ruby_xml_parser_enabled_xinclude_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_xpath?",
+			     ruby_xml_parser_enabled_xpath_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_xpointer?",
+			     ruby_xml_parser_enabled_xpointer_q, 0);
+  rb_define_singleton_method(cXMLParser, "enabled_zlib?",
+			     ruby_xml_parser_enabled_zlib_q, 0);
+
+  /* Other Class Methods */
+///  rb_define_singleton_method(cXMLParser, "register_deb",
+///			     ruby_register_deb, 0);
+
+	// TODO Maybe a set of 'xxxx_catalog' aliases might be more Ruby?
+  rb_define_singleton_method(cXMLParser, "catalog_dump",
+			     ruby_xml_parser_catalog_dump, 0);
+  rb_define_singleton_method(cXMLParser, "catalog_remove",
+			     ruby_xml_parser_catalog_remove, 1);
+  rb_define_singleton_method(cXMLParser, "check_lib_versions",
+			     ruby_xml_parser_check_lib_versions, 0);
+           
+  // TODO should this be debug_entities_q / debug_entities_set?
+  //      should all these default attribute pairs work that way?         
+  rb_define_singleton_method(cXMLParser, "debug_entities",
+			     ruby_xml_parser_debug_entities_get, 0);
+  rb_define_singleton_method(cXMLParser, "debug_entities=",
+			     ruby_xml_parser_debug_entities_set, 1);
+  rb_define_singleton_method(cXMLParser, "default_compression",
+			     ruby_xml_parser_default_compression_get, 0);
+  rb_define_singleton_method(cXMLParser, "default_compression=",
+			     ruby_xml_parser_default_compression_set, 1);
+  rb_define_singleton_method(cXMLParser, "default_keep_blanks",
+			     ruby_xml_parser_default_keep_blanks_get, 0);
+  rb_define_singleton_method(cXMLParser, "default_keep_blanks=",
+			     ruby_xml_parser_default_keep_blanks_set, 1);
+  rb_define_singleton_method(cXMLParser, "default_load_external_dtd",
+			     ruby_xml_parser_default_load_external_dtd_set, 0);
+  rb_define_singleton_method(cXMLParser, "default_load_external_dtd=",
+			     ruby_xml_parser_default_load_external_dtd_get, 1);
+  rb_define_singleton_method(cXMLParser, "default_line_numbers",
+			     ruby_xml_parser_default_line_numbers_get, 0);
+  rb_define_singleton_method(cXMLParser, "default_line_numbers=",
+			     ruby_xml_parser_default_line_numbers_set, 1);
+  rb_define_singleton_method(cXMLParser, "default_pedantic_parser",
+			     ruby_xml_parser_default_pedantic_parser_get, 0);
+  rb_define_singleton_method(cXMLParser, "default_pedantic_parser=",
+			     ruby_xml_parser_default_pedantic_parser_set, 1);
+  rb_define_singleton_method(cXMLParser, "default_substitute_entities",
+			     ruby_xml_parser_default_substitute_entities_get, 0);
+  rb_define_singleton_method(cXMLParser, "default_substitute_entities=",
+			     ruby_xml_parser_default_substitute_entities_set, 1);
+  rb_define_singleton_method(cXMLParser, "default_tree_indent_string",
+			     ruby_xml_parser_default_tree_indent_string_get, 0);
+  rb_define_singleton_method(cXMLParser, "default_tree_indent_string=",
+			     ruby_xml_parser_default_tree_indent_string_set, 1);
+  rb_define_singleton_method(cXMLParser, "default_validity_checking",
+			     ruby_xml_parser_default_validity_checking_get, 0);
+  rb_define_singleton_method(cXMLParser, "default_validity_checking=",
+			     ruby_xml_parser_default_validity_checking_set, 1);
+  rb_define_singleton_method(cXMLParser, "default_warnings",
+			     ruby_xml_parser_default_warnings_get, 0);
+  rb_define_singleton_method(cXMLParser, "default_warnings=",
+			     ruby_xml_parser_default_warnings_set, 1);
+			     
+  rb_define_singleton_method(cXMLParser, "features", ruby_xml_parser_features, 0);
+  rb_define_singleton_method(cXMLParser, "file", ruby_xml_parser_new_file, 1);
+  rb_define_singleton_method(cXMLParser, "indent_tree_output", ruby_xml_parser_indent_tree_output_get, 0);
+  rb_define_singleton_method(cXMLParser, "indent_tree_output=", ruby_xml_parser_indent_tree_output_set, 1);
+  rb_define_singleton_method(cXMLParser, "io", ruby_xml_parser_new_io, 1);
+  rb_define_singleton_method(cXMLParser, "memory_dump",
+			     ruby_xml_parser_memory_dump, 0);
+  rb_define_singleton_method(cXMLParser, "memory_used",
+			     ruby_xml_parser_memory_used, 0);
+  rb_define_singleton_method(cXMLParser, "new", ruby_xml_parser_new, 0);
+  rb_define_singleton_method(cXMLParser, "string", ruby_xml_parser_new_string, 1);
+  rb_define_singleton_method(cXMLParser, "register_error_handler", ruby_xml_parser_registerErrorHandler, 1);
+  rb_define_method(cXMLParser, "filename", ruby_xml_parser_filename_get, 0);
+  rb_define_method(cXMLParser, "filename=", ruby_xml_parser_filename_set, 1);
+  rb_define_method(cXMLParser, "io", ruby_xml_parser_io_get, 0);
+  rb_define_method(cXMLParser, "io=", ruby_xml_parser_io_set, 1);
+  rb_define_method(cXMLParser, "parse", ruby_xml_parser_parse, 0);
+  rb_define_method(cXMLParser, "parser_context", ruby_xml_parser_parser_context_get, 0);
+  rb_define_method(cXMLParser, "string", ruby_xml_parser_str_get, 0);
+  rb_define_method(cXMLParser, "string=", ruby_xml_parser_str_set, 1);
+  
+  // set up error handling
+  xmlSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
+  xmlThrDefSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
+  id_call = rb_intern("call");
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_parser.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_parser.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_parser.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,31 @@
+/* $Id: ruby_xml_parser.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_PARSER__
+#define __RUBY_XML_PARSER__
+
+#define MAX_LIBXML_FEATURES_LEN 50
+
+extern int ruby_xml_parser_count;
+extern VALUE cXMLParser;
+extern VALUE eXMLParserParseError;
+
+typedef struct ruby_xml_parser {
+  VALUE ctxt;
+  int parsed;
+  void *data;
+  int data_type;
+} ruby_xml_parser;
+
+VALUE ruby_xml_parser_default_load_external_dtd_set(VALUE class, VALUE bool);
+VALUE ruby_xml_parser_default_substitute_entities_set(VALUE class, VALUE bool);
+VALUE ruby_xml_parser_features(VALUE self);
+VALUE ruby_xml_parser_filename_get(VALUE self);
+VALUE ruby_xml_parser_filename_set(VALUE self, VALUE filename);
+VALUE ruby_xml_parser_new(VALUE class);
+VALUE ruby_xml_parser_parse(VALUE self);
+VALUE ruby_xml_parser_str_get(VALUE self);
+VALUE ruby_xml_parser_str_set(VALUE self, VALUE str);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_parser_context.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_parser_context.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_parser_context.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,715 @@
+/* $Id: ruby_xml_parser_context.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_parser_context.h"
+
+/* TODO:
+ *
+ * *) xmlParserInput class/structure
+ * *) errNo and mappings
+ * *) validity context
+ * *) record_info or stats class/structure
+ * *) xmlParserNodeInfoSeq
+ * *) xmlParserInputState
+ */
+VALUE cXMLParserContext;
+
+/*
+ * call-seq:
+ *    context.data_directory => "dir"
+ * 
+ * Obtain the data directory associated with this context.
+ */
+VALUE
+ruby_xml_parser_context_data_directory_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->directory == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2(rxpc->ctxt->directory));
+}
+
+
+/*
+ * call-seq:
+ *    context.depth => num
+ * 
+ * Obtain the depth of this context.
+ */
+VALUE
+ruby_xml_parser_context_depth_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->depth));
+}
+
+
+/*
+ * call-seq:
+ *    context.disable_sax? => (true|false)
+ * 
+ * Determine whether SAX-based processing is disabled
+ * in this context.
+ */
+VALUE
+ruby_xml_parser_context_disable_sax_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->disableSAX)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.doc => document
+ * 
+ * Obtain the +XML::Document+ associated with this context.
+ */
+VALUE
+ruby_xml_parser_context_doc_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->myDoc == NULL)
+    return(Qnil);
+
+  return(ruby_xml_document_new4(cXMLDocument, rxpc->ctxt->myDoc));
+}
+
+
+/*
+ * call-seq:
+ *    context.docbook? => (true|false)
+ * 
+ * Determine whether this is a docbook context.
+ */
+VALUE
+ruby_xml_parser_context_docbook_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->html == 2)    // TODO check this
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.encoding => "encoding"
+ * 
+ * Obtain the character encoding identifier used in
+ * this context.
+ */
+VALUE
+ruby_xml_parser_context_encoding_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->encoding == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxpc->ctxt->encoding));
+}
+
+
+/*
+ * call-seq:
+ *    context.errno => num
+ * 
+ * Obtain the last-error number in this context.
+ */
+VALUE
+ruby_xml_parser_context_errno_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->errNo));
+}
+
+
+void
+ruby_xml_parser_context_free(ruby_xml_parser_context *rxpc) {
+  if (rxpc->ctxt != NULL && !rxpc->is_ptr) {
+    xmlFreeParserCtxt(rxpc->ctxt);
+    ruby_xml_parser_count--;
+    rxpc->ctxt = NULL;
+  }
+
+  if (ruby_xml_parser_count == 0)
+    xmlCleanupParser();
+
+  free(rxpc);
+}
+
+
+/*
+ * call-seq:
+ *    context.html? => (true|false)
+ * 
+ * Determine whether this is an html context.
+ */
+VALUE
+ruby_xml_parser_context_html_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->html == 1)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.max_num_streams => num
+ * 
+ * Obtain the limit on the number of IO streams opened in
+ * this context.
+ */
+VALUE
+ruby_xml_parser_context_io_max_num_streams_get(VALUE self) {
+  // TODO alias to max_streams and dep this? 
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->inputMax));
+}
+
+
+/*
+ * call-seq:
+ *    context.num_streams => "dir"
+ * 
+ * Obtain the actual number of IO streams in this
+ * context.
+ */
+VALUE
+ruby_xml_parser_context_io_num_streams_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->inputNr));
+}
+
+
+/*
+ * call-seq:
+ *    context.keep_blanks? => (true|false)
+ * 
+ * Determine whether parsers in this context retain 
+ * whitespace.
+ */
+VALUE
+ruby_xml_parser_context_keep_blanks_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->keepBlanks)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.name_depth => num
+ * 
+ * Obtain the name depth for this context.
+ */
+VALUE
+ruby_xml_parser_context_name_depth_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->nameNr));
+}
+
+
+/*
+ * call-seq:
+ *    context.name_depth_max => num
+ * 
+ * Obtain the maximum name depth for this context.
+ */
+VALUE
+ruby_xml_parser_context_name_depth_max_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->nameMax));
+}
+
+
+/*
+ * call-seq:
+ *    context.name_node => "name"
+ * 
+ * Obtain the name node for this context.
+ */
+VALUE
+ruby_xml_parser_context_name_node_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->name == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxpc->ctxt->name));
+}
+
+
+/*
+ * call-seq:
+ *    context.name_tab => ["name", ..., "name"]
+ * 
+ * Obtain the name table for this context.
+ */
+VALUE
+ruby_xml_parser_context_name_tab_get(VALUE self) {
+  int i;
+  ruby_xml_parser_context *rxpc;
+  VALUE tab_ary;
+
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->nameTab == NULL)
+    return(Qnil);
+
+  tab_ary = rb_ary_new();
+
+  for (i = (rxpc->ctxt->nameNr - 1); i >= 0; i--) {
+    if (rxpc->ctxt->nameTab[i] == NULL)
+      continue;
+    else
+      rb_ary_push(tab_ary, rb_str_new2((const char*)rxpc->ctxt->nameTab[i]));
+  }
+
+  return(tab_ary);
+}
+
+
+/*
+ * call-seq:
+ *    context.node_depth => num
+ * 
+ * Obtain the node depth for this context.
+ */
+VALUE
+ruby_xml_parser_context_node_depth_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->nodeNr));
+}
+
+
+/*
+ * call-seq:
+ *    context.node => node
+ * 
+ * Obtain the root node of this context.
+ */
+VALUE
+ruby_xml_parser_context_node_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->node == NULL)
+    return(Qnil);
+  else
+    return(ruby_xml_node_new2(cXMLNode,
+			      ruby_xml_document_new(cXMLDocument, rxpc->ctxt->myDoc),
+			      rxpc->ctxt->node));
+}
+
+
+/*
+ * call-seq:
+ *    context.node_depth_max => num
+ * 
+ * Obtain the maximum node depth for this context.
+ */
+VALUE
+ruby_xml_parser_context_node_depth_max_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->nodeMax));
+}
+
+
+/*
+ * call-seq:
+ *    context.num_chars => num
+ * 
+ * Obtain the number of characters in this context.
+ */
+VALUE
+ruby_xml_parser_context_num_chars_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(LONG2NUM(rxpc->ctxt->nbChars));
+}
+
+
+VALUE
+ruby_xml_parser_context_new(VALUE class, xmlParserCtxtPtr ctxt) {
+  ruby_xml_parser_context *rxpc;
+
+  rxpc = ALLOC(ruby_xml_parser_context);
+  ruby_xml_parser_count++;
+
+  rxpc->ctxt = ctxt;
+  rxpc->is_ptr = 0;
+  return(Data_Wrap_Struct(class, 0, ruby_xml_parser_context_free, rxpc));
+}
+
+
+VALUE
+ruby_xml_parser_context_new2(VALUE class) {
+  return(ruby_xml_parser_context_new(class, NULL));
+}
+
+
+VALUE
+ruby_xml_parser_context_new3() {
+  return(ruby_xml_parser_context_new2(cXMLParserContext));
+}
+
+
+/*
+ * call-seq:
+ *    context.replace_entities? => (true|false)
+ * 
+ * Determine whether external entity replacement is enabled in this 
+ * context.
+ */
+VALUE
+ruby_xml_parser_context_replace_entities_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->replaceEntities)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.replace_entities = true|false
+ * 
+ * Control whether external entity replacement is enabled in this
+ * context.
+ */
+VALUE
+ruby_xml_parser_context_replace_entities_set(VALUE self, VALUE bool) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (TYPE(bool) == T_FALSE) {
+    rxpc->ctxt->replaceEntities = 0;
+    return(Qfalse);
+  } else {
+    rxpc->ctxt->replaceEntities = 1;
+    return(Qfalse);
+  }
+}
+
+
+/*
+ * call-seq:
+ *    context.space_depth => num
+ * 
+ * Obtain the space depth for this context.
+ */
+VALUE
+ruby_xml_parser_context_space_depth_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->spaceNr));
+}
+
+
+/*
+ * call-seq:
+ *    context.space_depth => num
+ * 
+ * Obtain the maximum space depth for this context.
+ */
+VALUE
+ruby_xml_parser_context_space_depth_max_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  return(INT2NUM(rxpc->ctxt->spaceMax));
+}
+
+
+/*
+ * call-seq:
+ *    context.subset_external? => (true|false)
+ * 
+ * Determine whether this context is a subset of an
+ * external context.
+ */
+VALUE
+ruby_xml_parser_context_subset_external_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->inSubset == 2)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.subset_internal? => (true|false)
+ * 
+ * Determine whether this context is a subset of an
+ * internal context.
+ */
+VALUE
+ruby_xml_parser_context_subset_internal_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->inSubset == 1)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.subset_name => "name"
+ * 
+ * Obtain this context's subset name (valid only if
+ * either of subset_external? or subset_internal?
+ * is true).
+ */
+VALUE
+ruby_xml_parser_context_subset_name_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->intSubName == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxpc->ctxt->intSubName));
+}
+
+
+/*
+ * call-seq:
+ *    context.subset_external_uri => "uri"
+ * 
+ * Obtain this context's external subset URI. (valid only if
+ * either of subset_external? or subset_internal?
+ * is true).
+ */
+VALUE
+ruby_xml_parser_context_subset_external_uri_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->extSubURI == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxpc->ctxt->extSubURI));
+}
+
+
+/*
+ * call-seq:
+ *    context.subset_external_system_id => "system_id"
+ * 
+ * Obtain this context's external subset system identifier. 
+ * (valid only if either of subset_external? or subset_internal?
+ * is true).
+ */
+VALUE
+ruby_xml_parser_context_subset_external_system_id_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->extSubSystem == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxpc->ctxt->extSubSystem));
+}
+
+
+/*
+ * call-seq:
+ *    context.standalone? => (true|false)
+ * 
+ * Determine whether this is a standalone context.
+ */
+VALUE
+ruby_xml_parser_context_standalone_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->standalone)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.stats? => (true|false)
+ * 
+ * Determine whether this context maintains statistics.
+ */
+VALUE
+ruby_xml_parser_context_stats_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->record_info)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.valid? => (true|false)
+ * 
+ * Determine whether this context is valid.
+ */
+VALUE
+ruby_xml_parser_context_valid_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->valid)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.validate? => (true|false)
+ * 
+ * Determine whether validation is enabled in this context.
+ */
+VALUE
+ruby_xml_parser_context_validate_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->validate)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+/*
+ * call-seq:
+ *    context.version => "version"
+ * 
+ * Obtain this context's version identifier.
+ */
+VALUE
+ruby_xml_parser_context_version_get(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->version == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxpc->ctxt->version));
+}
+
+
+/*
+ * call-seq:
+ *    context.well_formed? => (true|false)
+ * 
+ * Determine whether this context contains well-formed XML.
+ */
+VALUE
+ruby_xml_parser_context_well_formed_q(VALUE self) {
+  ruby_xml_parser_context *rxpc;
+  Data_Get_Struct(self, ruby_xml_parser_context, rxpc);
+
+  if (rxpc->ctxt->wellFormed)
+    return(Qtrue);
+  else
+    return(Qfalse);
+}
+
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+  cXMLParser = rb_define_class_under(mXML, "Parser", rb_cObject);
+#endif
+
+void
+ruby_init_xml_parser_context(void) {
+  cXMLParserContext = rb_define_class_under(cXMLParser, "Context", rb_cObject);
+
+  rb_define_method(cXMLParserContext, "data_directory", ruby_xml_parser_context_data_directory_get, 0);
+  rb_define_method(cXMLParserContext, "depth", ruby_xml_parser_context_depth_get, 0);
+  rb_define_method(cXMLParserContext, "disable_sax?", ruby_xml_parser_context_disable_sax_q, 0);
+  rb_define_method(cXMLParserContext, "doc", ruby_xml_parser_context_doc_get, 0);
+  rb_define_method(cXMLParserContext, "docbook?", ruby_xml_parser_context_docbook_q, 0);
+  rb_define_method(cXMLParserContext, "encoding", ruby_xml_parser_context_encoding_get, 0);
+  rb_define_method(cXMLParserContext, "errno", ruby_xml_parser_context_errno_get, 0);
+  rb_define_method(cXMLParserContext, "html?", ruby_xml_parser_context_html_q, 0);
+  rb_define_method(cXMLParserContext, "io_max_num_streams", ruby_xml_parser_context_io_max_num_streams_get, 0);
+  rb_define_method(cXMLParserContext, "io_num_streams", ruby_xml_parser_context_io_num_streams_get, 0);
+  rb_define_method(cXMLParserContext, "keep_blanks?", ruby_xml_parser_context_keep_blanks_q, 0);
+  rb_define_method(cXMLParserContext, "name_node", ruby_xml_parser_context_name_node_get, 0);
+  rb_define_method(cXMLParserContext, "name_depth", ruby_xml_parser_context_name_depth_get, 0);
+  rb_define_method(cXMLParserContext, "name_depth_max", ruby_xml_parser_context_name_depth_max_get, 0);
+  rb_define_method(cXMLParserContext, "name_tab", ruby_xml_parser_context_name_tab_get, 0);
+  rb_define_method(cXMLParserContext, "node", ruby_xml_parser_context_node_get, 0);
+  rb_define_method(cXMLParserContext, "node_depth", ruby_xml_parser_context_node_depth_get, 0);
+  rb_define_method(cXMLParserContext, "node_depth_max", ruby_xml_parser_context_node_depth_max_get, 0);
+  rb_define_method(cXMLParserContext, "num_chars", ruby_xml_parser_context_num_chars_get, 0);
+  rb_define_method(cXMLParserContext, "replace_entities?", ruby_xml_parser_context_replace_entities_q, 0);
+  rb_define_method(cXMLParserContext, "replace_entities=", ruby_xml_parser_context_replace_entities_set, 1);
+  rb_define_method(cXMLParserContext, "space_depth", ruby_xml_parser_context_space_depth_get, 0);
+  rb_define_method(cXMLParserContext, "space_depth_max", ruby_xml_parser_context_space_depth_max_get, 0);
+  rb_define_method(cXMLParserContext, "subset_external?", ruby_xml_parser_context_subset_external_q, 0);
+  rb_define_method(cXMLParserContext, "subset_external_system_id", ruby_xml_parser_context_subset_external_system_id_get, 0);
+  rb_define_method(cXMLParserContext, "subset_external_uri", ruby_xml_parser_context_subset_name_get, 0);
+  rb_define_method(cXMLParserContext, "subset_internal?", ruby_xml_parser_context_subset_internal_q, 0);
+  rb_define_method(cXMLParserContext, "subset_internal_name", ruby_xml_parser_context_subset_name_get, 0);
+  rb_define_method(cXMLParserContext, "stats?", ruby_xml_parser_context_stats_q, 0);
+  rb_define_method(cXMLParserContext, "standalone?", ruby_xml_parser_context_standalone_q, 0);
+  rb_define_method(cXMLParserContext, "valid", ruby_xml_parser_context_valid_q, 0);
+  rb_define_method(cXMLParserContext, "validate?", ruby_xml_parser_context_validate_q, 0);
+  rb_define_method(cXMLParserContext, "version", ruby_xml_parser_context_version_get, 0);
+  rb_define_method(cXMLParserContext, "well_formed?", ruby_xml_parser_context_well_formed_q, 0);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_parser_context.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_parser_context.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_parser_context.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,22 @@
+/* $Id: ruby_xml_parser_context.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_PARSER_CONTEXT__
+#define __RUBY_XML_PARSER_CONTEXT__
+
+extern VALUE cXMLParserContext;
+
+typedef struct ruby_xml_parser_context {
+  xmlParserCtxtPtr ctxt;
+  int is_ptr;
+} ruby_xml_parser_context;
+
+void ruby_xml_parser_context_free(ruby_xml_parser_context *ctxt);
+void ruby_init_xml_parser_context(void);
+VALUE ruby_xml_parser_context_new(VALUE class, xmlParserCtxtPtr ctxt);
+VALUE ruby_xml_parser_context_new2(VALUE class);
+VALUE ruby_xml_parser_context_new3();
+VALUE ruby_xml_parser_context_each(VALUE self);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_sax_parser.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_sax_parser.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_sax_parser.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,426 @@
+/* $Id: ruby_xml_sax_parser.c,v 1.4 2006/04/14 23:46:06 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_sax_parser.h"
+
+VALUE cXMLSaxParser;
+VALUE callsym;
+
+#include "sax_parser_callbacks.inc"
+
+void
+ruby_xml_sax_parser_free(ruby_xml_sax_parser *rxsp) {
+  /* Apparently this isn't needed: time will tell */
+  /* if (rxsp->xsh != NULL) */
+  /* xmlFreeSax_Parser(rxsp->sax_parser); */
+}
+
+#define mark_handler(rxsp, handler) \
+    if (rxsp->cbp->handler && (rxsp->cbp->handler != Qnil)) \
+      rb_gc_mark(rxsp->cbp->handler)
+  
+void
+ruby_xml_sax_parser_mark(ruby_xml_sax_parser *rxsp) {
+  mark_handler(rxsp, internalSubset);
+  mark_handler(rxsp, isStandalone);
+  mark_handler(rxsp, hasInternalSubset);
+  mark_handler(rxsp, hasExternalSubset);
+  mark_handler(rxsp, startDocument);
+  mark_handler(rxsp, endDocument);
+  mark_handler(rxsp, startElement);
+  mark_handler(rxsp, endElement);
+  mark_handler(rxsp, reference);
+  mark_handler(rxsp, characters);
+  mark_handler(rxsp, processingInstruction);
+  mark_handler(rxsp, comment);
+  mark_handler(rxsp, xmlParserWarning);
+  mark_handler(rxsp, xmlParserError);
+  mark_handler(rxsp, xmlParserFatalError);
+  mark_handler(rxsp, cdataBlock);
+}
+
+
+/*
+ * call-seq:
+ *    XML::SaxParser.new => sax_parser
+ * 
+ * Create a new XML::SaxParser instance.
+ */
+VALUE
+ruby_xml_sax_parser_new(VALUE class) {
+  ruby_xml_sax_parser *rxsp;
+  
+  rxsp = ALLOC(ruby_xml_sax_parser);
+  rxsp->cbp = ALLOC(ruby_xml_sax_parser_callbacks);
+  memset(rxsp->cbp, 0, sizeof(ruby_xml_sax_parser_callbacks));
+  rxsp->xsh = &rubySAXHandlerStruct;
+  
+  rxsp->xpc = NULL;
+  rxsp->filename = Qnil;
+  rxsp->str = Qnil;
+
+  return(Data_Wrap_Struct(class, ruby_xml_sax_parser_mark, 
+                              ruby_xml_sax_parser_free, rxsp));
+}
+
+
+/*
+ * call-seq:
+ *    sax_parser.filename => "filename"
+ * 
+ * Obtain the filename this parser reads from.
+ */
+VALUE
+ruby_xml_sax_parser_filename_get(VALUE self) {
+  ruby_xml_sax_parser *rxsp;
+  Data_Get_Struct(self, ruby_xml_sax_parser, rxsp);
+  return(rxsp->filename);
+}
+
+
+/*
+ * call-seq:
+ *    sax_parser.filename = "filename"
+ * 
+ * Set the filename this parser reads from.
+ */
+VALUE
+ruby_xml_sax_parser_filename_set(VALUE self, VALUE filename) {
+  ruby_xml_sax_parser *rxsp;
+  Check_Type(filename, T_STRING);
+  Data_Get_Struct(self, ruby_xml_sax_parser, rxsp);
+  rxsp->filename = filename;
+  return(rxsp->filename);
+}
+
+#define set_handler(self, argc, argv, handler)      \
+  VALUE proc;                                       \
+  rb_scan_args(argc, argv, "0&", &proc);            \
+  ruby_xml_sax_parser *rxsp;                        \
+  Data_Get_Struct(self, ruby_xml_sax_parser, rxsp); \
+  rxsp->cbp->handler = proc;                        \
+  return(Qnil);
+
+
+/*
+ * call-seq:
+ *    parser.on_internal_subset { |name, external_id, system_id| ... } => nil
+ *
+ * Set the callback block for an internal subset event.
+ */
+VALUE
+ruby_xml_sax_parser_on_internal_subset(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, internalSubset);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_is_standalone { || ... } => nil
+ *
+ * Set the callback proc for 'is standalone' event.
+ */
+VALUE
+ruby_xml_sax_parser_on_is_standalone(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, isStandalone);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_has_internal_subset { || ... } => nil
+ *
+ * Set the callback proc for an internal subset notification event.
+ */
+VALUE
+ruby_xml_sax_parser_on_has_internal_subset(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, hasInternalSubset);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_has_external_subset { || ... } => nil
+ *
+ * Set the callback proc for an external subset notification event.
+ */
+VALUE
+ruby_xml_sax_parser_on_has_external_subset(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, hasExternalSubset);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_start_document { || ... } => nil
+ *
+ * Set the callback proc for a start document event.
+ */
+VALUE
+ruby_xml_sax_parser_on_start_document(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, startDocument);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_end_document { || ... } => nil
+ *
+ * Set the callback proc for an end document event.
+ */
+VALUE
+ruby_xml_sax_parser_on_end_document(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, endDocument);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_start_element { |name, attr_hash| ... } => nil
+ * 
+ * Set the callback proc for an element start event.
+ */
+VALUE
+ruby_xml_sax_parser_on_start_element(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, startElement);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_end_element { |name| ... } => nil
+ *
+ * Set the callback proc for an element end event.
+ */
+VALUE
+ruby_xml_sax_parser_on_end_element(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, endElement);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_reference { |name| ... } => nil
+ *
+ * Set the callback proc for a reference event.
+ */
+VALUE
+ruby_xml_sax_parser_on_reference(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, reference);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_characters { |chars| ... } => nil
+ *
+ * Set the callback proc for a characters event.
+ */
+VALUE
+ruby_xml_sax_parser_on_characters(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, characters);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_processing_instruction { |target, data| ... } => nil
+ *
+ * Set the callback proc for an processing instruction event.
+ */
+VALUE
+ruby_xml_sax_parser_on_processing_instruction(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, processingInstruction);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_comment { |msg| ... } => nil
+ *
+ * Set the callback proc for a comment event.
+ */
+VALUE
+ruby_xml_sax_parser_on_comment(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, comment);
+}
+
+
+/*
+ * call-seq:
+ *    parser.on_parser_warning { |msg| ... } => nil
+ *
+ * Set the callback proc that receives parser warnings.
+ */
+VALUE
+ruby_xml_sax_parser_on_parser_warning(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, xmlParserWarning);
+}
+ 
+ 
+/*
+ * call-seq:
+ *    parser.on_parser_error { |msg| ... } => nil
+ *
+ * Set the callback proc that receives parser errors.
+ */
+VALUE
+ruby_xml_sax_parser_on_parser_error(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, xmlParserError);
+}
+ 
+  
+/*
+ * call-seq:
+ *    parser.on_parser_fatal_error { |msg| ... } => nil
+ *
+ * Set the callback proc that receives fatal parser errors.
+ */
+VALUE
+ruby_xml_sax_parser_on_parser_fatal_error(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, xmlParserFatalError);
+}
+ 
+/*
+ * call-seq:
+ *    parser.on_cdata_block { |cdata| ... } => nil
+ *
+ * Set the callback proc for a CDATA block event.
+ */
+VALUE
+ruby_xml_sax_parser_on_cdata_block(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, cdataBlock);
+}
+ 
+/*
+ * call-seq:
+ *    parser.on_external_subset { |name, external_id, system_id| ... } => nil
+ *
+ * Set the callback proc for an external subset event.
+ */
+VALUE
+ruby_xml_sax_parser_on_external_subset(int argc, VALUE *argv, VALUE self) {
+  set_handler(self, argc, argv, externalSubset);
+}
+ 
+  
+/*
+ * call-seq:
+ *    parser.parse => (true|false)
+ * 
+ * Parse the input XML, generating callbacks to the procs
+ * registered with the parser (via the on_xxxx attributes).
+ */
+VALUE
+ruby_xml_sax_parser_parse(VALUE self) {
+  char *str;
+  int status = 1;
+  ruby_xml_sax_parser *rxsp;
+
+  Data_Get_Struct(self, ruby_xml_sax_parser, rxsp);
+
+  if (rxsp->filename != Qnil) {
+    status = xmlSAXUserParseFile(rxsp->xsh, rxsp->cbp, StringValuePtr(rxsp->filename));
+  } else if (rxsp->str != Qnil) {
+    str = StringValuePtr(rxsp->str);
+    status = //ruby_xml_document_new(cXMLDocument,
+				   xmlSAXUserParseMemory(rxsp->xsh, rxsp->cbp,
+                 str, strlen(str)); //);
+  }
+  
+  /* XXX This should return an exception for the various error codes
+   * that can come back in status, but I'm too lazy to do that right
+   * now. */
+  if (status)
+    return(Qfalse);
+  else
+    return(Qtrue);
+}
+
+
+/*
+ * call-seq:
+ *    parser.string => "xml"
+ * 
+ * Obtain the parser's input string.
+ */
+VALUE
+ruby_xml_sax_parser_str_get(VALUE self) {
+  ruby_xml_sax_parser *rxsp;
+  Data_Get_Struct(self, ruby_xml_sax_parser, rxsp);
+  return(rxsp->str);
+}
+
+
+/*
+ * call-seq:
+ *    parser.string = "xml"
+ * 
+ * Set the parser's input string.
+ */
+VALUE
+ruby_xml_sax_parser_str_set(VALUE self, VALUE str) {
+  ruby_xml_sax_parser *rxsp;
+  Check_Type(str, T_STRING);
+  Data_Get_Struct(self, ruby_xml_sax_parser, rxsp);
+  rxsp->str = str;
+  return(rxsp->str);
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_sax_parser(void) {
+  cXMLSaxParser = rb_define_class_under(mXML, "SaxParser", rb_cObject);
+  callsym = rb_intern("call");
+
+  rb_define_singleton_method(cXMLSaxParser, "new", ruby_xml_sax_parser_new, 0);
+
+  rb_define_method(cXMLSaxParser, "filename",
+		   ruby_xml_sax_parser_filename_get, 0);
+  rb_define_method(cXMLSaxParser, "filename=",
+		   ruby_xml_sax_parser_filename_set, 1);
+  rb_define_method(cXMLSaxParser, "parse", ruby_xml_sax_parser_parse, 0);
+  rb_define_method(cXMLSaxParser, "string", ruby_xml_sax_parser_str_get, 0);
+  rb_define_method(cXMLSaxParser, "string=", ruby_xml_sax_parser_str_set, 1);
+
+  rb_define_method(cXMLSaxParser, "on_internal_subset", 
+      ruby_xml_sax_parser_on_internal_subset, -1);        
+  rb_define_method(cXMLSaxParser, "on_is_standalone", 
+      ruby_xml_sax_parser_on_is_standalone, -1);        
+  rb_define_method(cXMLSaxParser, "on_has_internal_subset", 
+      ruby_xml_sax_parser_on_has_internal_subset, -1);        
+  rb_define_method(cXMLSaxParser, "on_has_external_subset", 
+      ruby_xml_sax_parser_on_has_external_subset, -1);        
+  rb_define_method(cXMLSaxParser, "on_start_document", 
+      ruby_xml_sax_parser_on_start_document, -1);  
+  rb_define_method(cXMLSaxParser, "on_end_document", 
+      ruby_xml_sax_parser_on_end_document, -1);  
+  rb_define_method(cXMLSaxParser, "on_start_element", 
+      ruby_xml_sax_parser_on_start_element, -1);  
+  rb_define_method(cXMLSaxParser, "on_end_element", 
+      ruby_xml_sax_parser_on_end_element, -1);        
+  rb_define_method(cXMLSaxParser, "on_reference", 
+      ruby_xml_sax_parser_on_reference, -1);        
+  rb_define_method(cXMLSaxParser, "on_characters", 
+      ruby_xml_sax_parser_on_characters, -1);        
+  rb_define_method(cXMLSaxParser, "on_processing_instruction", 
+      ruby_xml_sax_parser_on_processing_instruction, -1);        
+  rb_define_method(cXMLSaxParser, "on_comment", 
+      ruby_xml_sax_parser_on_comment, -1);        
+  rb_define_method(cXMLSaxParser, "on_parser_warning", 
+      ruby_xml_sax_parser_on_parser_warning, -1);        
+  rb_define_method(cXMLSaxParser, "on_parser_error", 
+      ruby_xml_sax_parser_on_parser_error, -1);        
+  rb_define_method(cXMLSaxParser, "on_parser_fatal_error", 
+      ruby_xml_sax_parser_on_parser_fatal_error, -1);        
+  rb_define_method(cXMLSaxParser, "on_cdata_block", 
+      ruby_xml_sax_parser_on_cdata_block, -1);        
+  rb_define_method(cXMLSaxParser, "on_external_subset", 
+      ruby_xml_sax_parser_on_external_subset, -1);              
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_sax_parser.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_sax_parser.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_sax_parser.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,52 @@
+/* $Id: ruby_xml_sax_parser.h,v 1.2 2006/04/14 14:45:52 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_SAX_PARSER__
+#define __RUBY_XML_SAX_PARSER__
+
+extern VALUE cXMLSaxParser;
+
+typedef struct ruby_xml_sax_parser_callbacks {
+    VALUE internalSubset;
+    VALUE isStandalone;
+    VALUE hasInternalSubset;
+    VALUE hasExternalSubset;
+    VALUE resolveEntity;
+    VALUE getEntity;
+    VALUE entityDecl;
+    VALUE notationDecl;
+    VALUE attributeDecl;
+    VALUE elementDecl;
+    VALUE unparsedEntityDecl;
+    VALUE setDocumentLocator;
+    VALUE startDocument;
+    VALUE endDocument;
+    VALUE startElement;
+    VALUE endElement;
+    VALUE reference;
+    VALUE characters;
+    VALUE ignorableWhitespace;
+    VALUE processingInstruction;
+    VALUE comment;
+    VALUE xmlParserWarning;
+    VALUE xmlParserError;
+    VALUE xmlParserFatalError;
+    VALUE getParameterEntity;
+    VALUE cdataBlock;
+    VALUE externalSubset;  
+} ruby_xml_sax_parser_callbacks;
+
+typedef struct ruby_xml_sax_parser {
+  xmlParserCtxtPtr xpc;
+  xmlSAXHandlerPtr xsh;
+  ruby_xml_sax_parser_callbacks *cbp;
+  VALUE filename;
+  VALUE str;
+} ruby_xml_sax_parser;
+
+void ruby_xml_sax_parser_free(ruby_xml_sax_parser *rxsp);
+void ruby_init_xml_sax_parser(void);
+VALUE ruby_xml_sax_parser_new(VALUE class);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_schema.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_schema.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_schema.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,142 @@
+#include "libxml.h"
+#include "ruby_xml_schema.h"
+
+VALUE cXMLSchema;
+
+static void
+ruby_xml_schema_mark(ruby_xml_schema *rxschema) {
+  return;
+}
+
+void
+ruby_xml_schema_free(ruby_xml_schema *rxschema) {
+  if (rxschema->schema != NULL) {
+    xmlSchemaFree(rxschema->schema);
+    rxschema->schema = NULL;
+  }
+
+  free(rxschema);
+}
+
+/*
+ * call-seq:
+ *    XML::Schema.new(schema_uri) => schema
+ * 
+ * Create a new schema from the specified URI.
+ */
+VALUE
+ruby_xml_schema_init_from_uri(int argc, VALUE *argv, VALUE class) {
+  VALUE uri;
+  xmlSchemaParserCtxtPtr parser;
+  xmlSchemaPtr sptr;
+
+  switch (argc) {
+  case 1:
+    rb_scan_args(argc, argv, "10", &uri);
+
+    Check_Type(uri, T_STRING);
+
+ 	parser = xmlSchemaNewParserCtxt(StringValuePtr(uri));
+ 	sptr = xmlSchemaParse(parser);
+ 	xmlSchemaFreeParserCtxt(parser);
+    break;
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (need 1)");
+  }
+  return Qnil;
+}
+
+/*
+ * call-seq:
+ *    XML::Schema.from_string("schema_data") => "value"
+ * 
+ * Create a new schema using the specified string.
+ */
+VALUE
+ruby_xml_schema_init_from_str(int argc, VALUE *argv, VALUE class) {
+  VALUE schema_str;
+
+  xmlSchemaParserCtxtPtr  parser;
+  //xmlSchemaPtr            sptr;
+  ruby_xml_schema *rxschema;
+
+  switch (argc) {
+  case 1:
+    rb_scan_args(argc, argv, "10", &schema_str);
+
+    Check_Type(schema_str, T_STRING);
+
+    parser = xmlSchemaNewMemParserCtxt(StringValuePtr(schema_str), strlen(StringValuePtr(schema_str)));
+    rxschema = ALLOC(ruby_xml_schema);
+    rxschema->schema = xmlSchemaParse(parser);
+ 	xmlSchemaFreeParserCtxt(parser);
+
+    return( Data_Wrap_Struct(cXMLSchema, ruby_xml_schema_mark, ruby_xml_schema_free, rxschema) );
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (need 1)");
+  }
+  return Qnil;
+}
+  
+/* TODO what is this patch doing here?
+ 
+ 	xmlSchemaParserCtxtPtr  parser;
+ 	xmlSchemaPtr            sptr;
+ 	xmlSchemaValidCtxtPtr   vptr;
++	int                     is_invalid;
+ 	
+ 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &source) == FAILURE) {
+ 		return;
+@@ -598,26 +598,24 @@
+ 			convert_to_string_ex(&source);
+ 			parser = xmlSchemaNewParserCtxt(Z_STRVAL_P(source));
+ 			sptr = xmlSchemaParse(parser);
+ 			break;
+ 		case SCHEMA_BLOB:
+ 			convert_to_string_ex(&source);
+ 			parser = xmlSchemaNewMemParserCtxt(Z_STRVAL_P(source), Z_STRLEN_P(source));
+ 			sptr = xmlSchemaParse(parser);
+ 			break;
+ 	}
+ 
+ 	vptr = xmlSchemaNewValidCtxt(sptr);
++	is_invalid = xmlSchemaValidateDoc(vptr, (xmlDocPtr) sxe->document->ptr);
+ 	xmlSchemaFree(sptr);
+ 	xmlSchemaFreeValidCtxt(vptr);
+ 	xmlSchemaFreeParserCtxt(parser);
+ 
+-	if (is_valid) {
+-		RETURN_TRUE;
+-	} else {
++	if (is_invalid) {
+ 		RETURN_FALSE;
++	} else {
++		RETURN_TRUE;
+ 	}
+ }
+  }}} 
+@@ -695,7 +693,7 @@
+ {
+ 	if (!strcmp(method, "xsearch")) {
+ 		simplexml_ce_xpath_search(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+-#ifdef xmlSchemaParserCtxtPtr
++#ifdef LIBXML_SCHEMAS_ENABLED
+ 	} else if (!strcmp(method, "validate_schema_file")) {
+ 		simplexml_ce_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, SCHEMA_FILE);	
+ 	} else if (!strcmp(method, "validate_schema_buffer")) {
+*/
+
+void  ruby_schema_free(ruby_xml_schema *rxs) {
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void  ruby_init_xml_schema(void) {
+  cXMLSchema = rb_define_class_under(mXML, "Schema", rb_cObject);
+  rb_define_singleton_method(cXMLSchema, "new",         ruby_xml_schema_init_from_uri, -1);
+  rb_define_singleton_method(cXMLSchema, "from_string", ruby_xml_schema_init_from_str, -1);
+}
+

Added: packages-wip/libxml-ruby/trunk/ruby_xml_schema.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_schema.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_schema.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,16 @@
+#ifndef __RUBY_XML_SCHEMA__
+#define __RUBY_XML_SCHEMA__
+
+#include <libxml/schemasInternals.h>
+#include <libxml/xmlschemas.h>
+
+extern VALUE cXMLSchema;
+
+typedef struct rxp_schema {
+  xmlSchemaPtr schema;   /* Schema interface */
+} ruby_xml_schema;
+
+void  ruby_init_xml_schema(void);
+void  ruby_schema_free(ruby_xml_schema *rxs);
+#endif
+

Added: packages-wip/libxml-ruby/trunk/ruby_xml_tree.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_tree.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_tree.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,43 @@
+/* $Id: ruby_xml_tree.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_tree.h"
+
+VALUE cXMLTree;
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_tree(void) {
+  cXMLTree = rb_define_class_under(mXML, "Tree", rb_cObject);
+
+  rb_define_const(cXMLTree, "ELEMENT_NODE", INT2FIX(XML_ELEMENT_NODE));
+  rb_define_const(cXMLTree, "ATTRIBUTE_NODE", INT2FIX(XML_ATTRIBUTE_NODE));
+  rb_define_const(cXMLTree, "TEXT_NODE", INT2FIX(XML_TEXT_NODE));
+  rb_define_const(cXMLTree, "CDATA_SECTION_NODE", INT2FIX(XML_CDATA_SECTION_NODE));
+  rb_define_const(cXMLTree, "ENTITY_REF_NODE", INT2FIX(XML_ENTITY_REF_NODE));
+  rb_define_const(cXMLTree, "ENTITY_NODE", INT2FIX(XML_ENTITY_NODE));
+  rb_define_const(cXMLTree, "PI_NODE", INT2FIX(XML_PI_NODE));
+  rb_define_const(cXMLTree, "COMMENT_NODE", INT2FIX(XML_COMMENT_NODE));
+  rb_define_const(cXMLTree, "DOCUMENT_NODE", INT2FIX(XML_DOCUMENT_NODE));
+  rb_define_const(cXMLTree, "DOCUMENT_TYPE_NODE", INT2FIX(XML_DOCUMENT_TYPE_NODE));
+  rb_define_const(cXMLTree, "DOCUMENT_FRAG_NODE", INT2FIX(XML_DOCUMENT_FRAG_NODE));
+  rb_define_const(cXMLTree, "NOTATION_NODE", INT2FIX(XML_NOTATION_NODE));
+  rb_define_const(cXMLTree, "HTML_DOCUMENT_NODE", INT2FIX(XML_HTML_DOCUMENT_NODE));
+  rb_define_const(cXMLTree, "DTD_NODE", INT2FIX(XML_DTD_NODE));
+  rb_define_const(cXMLTree, "ELEMENT_DECL", INT2FIX(XML_ELEMENT_DECL));
+  rb_define_const(cXMLTree, "ATTRIBUTE_DECL", INT2FIX(XML_ATTRIBUTE_DECL));
+  rb_define_const(cXMLTree, "ENTITY_DECL", INT2FIX(XML_ENTITY_DECL));
+  rb_define_const(cXMLTree, "NAMESPACE_DECL", INT2FIX(XML_NAMESPACE_DECL));
+  rb_define_const(cXMLTree, "XINCLUDE_START", INT2FIX(XML_XINCLUDE_START));
+  rb_define_const(cXMLTree, "XINCLUDE_END", INT2FIX(XML_XINCLUDE_END));
+
+#ifdef LIBXML_DOCB_ENABLED
+  rb_define_const(cXMLTree, "DOCB_DOCUMENT_NODE", INT2FIX(XML_DOCB_DOCUMENT_NODE));
+#endif
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_tree.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_tree.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_tree.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,12 @@
+/* $Id: ruby_xml_tree.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_TREE__
+#define __RUBY_XML_TREE__
+
+extern VALUE cXMLTree;
+
+void ruby_init_xml_tree(void);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xinclude.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xinclude.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xinclude.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,20 @@
+/* $Id: ruby_xml_xinclude.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_xinclude.h"
+
+VALUE cXMLXInclude;
+VALUE eXMLXIncludeError;
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_xinclude(void) {
+  cXMLXInclude = rb_define_class_under(mXML, "XInclude", rb_cObject);
+  eXMLXIncludeError = rb_define_class_under(cXMLXInclude, "Error", rb_eRuntimeError);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xinclude.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xinclude.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xinclude.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,13 @@
+/* $Id: ruby_xml_xinclude.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_XINCLUDE__
+#define __RUBY_XML_XINCLUDE__
+
+extern VALUE cXMLXInclude;
+extern VALUE eXMLXIncludeError;
+
+void ruby_init_xml_xinclude(void);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xpath.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xpath.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xpath.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,363 @@
+/* $Id: ruby_xml_xpath.c,v 1.2 2006/04/14 14:45:25 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_xpath.h"
+
+/*
+ * Document-class: XML::XPath
+ * 
+ * Includes Enumerable.
+ */
+VALUE cXMLXPath;
+VALUE eXMLXPathInvalidPath;
+
+#ifdef LIBXML_XPATH_ENABLED
+
+/*
+ * call-seq:
+ *    xpath.debug => (true|false)
+ * 
+ * Dump libxml debugging information to stdout.
+ * Requires Libxml be compiled with debugging enabled.
+ */
+VALUE
+ruby_xml_xpath_debug(VALUE self) {
+#ifdef LIBXML_DEBUG_ENABLED
+  ruby_xml_xpath *rxxp;
+  Data_Get_Struct(self, ruby_xml_xpath, rxxp);
+
+  if (rxxp->xpop != NULL) {
+    xmlXPathDebugDumpObject(stdout, rxxp->xpop, 0);
+    return(Qtrue);
+  } else {
+    return(Qfalse);
+  }
+#else
+  rb_warn("libxml does not have debugging turned on");
+  return(Qfalse);
+#endif
+}
+
+// TODO Maybe we should support [] or some other kind of access if poss.
+
+/*
+ * call-seq:
+ *    xpath.each { |node| ... } => self
+ * 
+ * Call the supplied block for each matching node.
+ */
+VALUE
+ruby_xml_xpath_each(VALUE self) {
+  ruby_xml_xpath *rxxp;
+  VALUE rxnset;
+
+  Data_Get_Struct(self, ruby_xml_xpath, rxxp);
+
+  if (rxxp->xpop == NULL || rxxp->xpop->type != XPATH_NODESET)
+    return(Qnil);
+
+  rxnset = ruby_xml_node_set_new(cXMLNodeSet, rxxp->xd, self,
+				 rxxp->xpop->nodesetval);
+  ruby_xml_node_set_each(rxnset);
+  return(rxnset);
+}
+
+///////////////////////////////////////////////////
+// TODO xpath_find is throwing TypeError:
+//
+//    TypeError: can't convert nil into String
+//
+// When given a namespace when non exist.
+
+/*
+ * call-seq:
+ *    XML::XPath.find(path, namespaces = [any]) => xpath
+ * 
+ * Find nodes matching the specified xpath (and optionally any of the
+ * supplied namespaces) and return as an XML::Node::Set.
+ * 
+ * The optional namespaces argument may take one of
+ * two forms:
+ * 
+ * * A string in the form of: "prefix:uri", or
+ * * An array of:
+ *   * strings in the form like above
+ *   * arrays in the form of ['prefix','uri']
+ * 
+ * If not specified, matching nodes from any namespace
+ * will be included.
+ */
+VALUE
+ruby_xml_xpath_find(int argc, VALUE *argv, VALUE class) {
+#ifdef LIBXML_XPATH_ENABLED
+  xmlXPathCompExprPtr comp;
+  ruby_xml_node *node;
+  ruby_xml_xpath *rxxp;
+  ruby_xml_xpath_context *rxxpc;
+  ruby_xml_ns *rxns;
+  VALUE rnode, rprefix, ruri, xxpc, xpath, xpath_expr;
+  char *cp;
+  long i;
+
+  switch(argc) {
+  case 3:
+    /* array of namespaces we allow.
+     *
+     * Accept either:
+     *   A string in the form of: "prefix:uri", or
+     *   An array of:
+     *     *) strings in the form like above
+     *     *) arrays in the form of ['prefix','uri']
+     */
+
+    /* Intentionally fall through, we deal with the last arg below
+     * after the XPathContext object has been setup */
+  case 2:
+    rnode = argv[0];
+    xpath_expr = argv[1];
+    break;
+  default:
+    rb_raise(rb_eArgError, "wrong number of arguments (1 or 2)");
+  }
+
+  Data_Get_Struct(rnode, ruby_xml_node, node);
+
+  xxpc = ruby_xml_xpath_context_new4(rnode);
+  if (NIL_P(xxpc))
+    return(Qnil);
+  Data_Get_Struct(xxpc, ruby_xml_xpath_context, rxxpc);
+
+  xpath = ruby_xml_xpath_new(cXMLXPath, rnode, xxpc, NULL);
+  Data_Get_Struct(xpath, ruby_xml_xpath, rxxp);
+
+  rxxpc->ctxt->node = node->node;
+  if (node->node->type == XML_DOCUMENT_NODE) {
+    rxxpc->ctxt->namespaces = xmlGetNsList(node->node->doc,
+					   xmlDocGetRootElement(node->node->doc));
+  } else {
+    rxxpc->ctxt->namespaces = xmlGetNsList(node->node->doc, node->node);
+  }
+
+  rxxpc->ctxt->nsNr = 0;
+  if (rxxpc->ctxt->namespaces != NULL) {
+    while (rxxpc->ctxt->namespaces[rxxpc->ctxt->nsNr] != NULL)
+      rxxpc->ctxt->nsNr++;
+  }
+
+  /* Need to loop through the 2nd argument and iterate through the
+   * list of namespaces that we want to allow */
+  if (argc == 3) {
+    switch (TYPE(argv[2])) {
+    case T_STRING:
+      cp = strchr(StringValuePtr(argv[2]), (int)':');
+      if (cp == NULL) {
+	rprefix = argv[2];
+	ruri = Qnil;
+      } else {
+	rprefix = rb_str_new(StringValuePtr(argv[2]), (int)((long)cp - (long)StringValuePtr(argv[2])));
+	ruri = rb_str_new2(&cp[1]);
+      }
+      /* Should test the results of this */
+      ruby_xml_xpath_context_register_namespace(xxpc, rprefix, ruri);
+      break;
+    case T_ARRAY:
+      for (i = 0; i < RARRAY(argv[2])->len; i++) {
+	switch (TYPE(RARRAY(argv[2])->ptr[i])) {
+	case T_STRING:
+	  cp = strchr(StringValuePtr(RARRAY(argv[2])->ptr[i]), (int)':');
+	  if (cp == NULL) {
+	    rprefix = RARRAY(argv[2])->ptr[i];
+	    ruri = Qnil;
+	  } else {
+	    rprefix = rb_str_new(StringValuePtr(RARRAY(argv[2])->ptr[i]), (int)((long)cp - (long)StringValuePtr(RARRAY(argv[2])->ptr[i])));
+	    ruri = rb_str_new2(&cp[1]);
+	  }
+	  /* Should test the results of this */
+	  ruby_xml_xpath_context_register_namespace(xxpc, rprefix, ruri);
+	  break;
+	case T_ARRAY:
+	  if (RARRAY(RARRAY(argv[2])->ptr[i])->len == 2) {
+	    rprefix = RARRAY(RARRAY(argv[2])->ptr[i])->ptr[0];
+	    ruri = RARRAY(RARRAY(argv[2])->ptr[i])->ptr[1];
+	    ruby_xml_xpath_context_register_namespace(xxpc, rprefix, ruri);
+	  } else {
+	    rb_raise(rb_eArgError, "nested array must be an array of strings, prefix and href/uri");
+	  }
+	  break;
+	default:
+	  if (rb_obj_is_kind_of(RARRAY(argv[2])->ptr[i], cXMLNS) == Qtrue) {
+	    Data_Get_Struct(argv[2], ruby_xml_ns, rxns);
+	    rprefix = rb_str_new2((const char*)rxns->ns->prefix);
+	    ruri = rb_str_new2((const char*)rxns->ns->href);
+	    ruby_xml_xpath_context_register_namespace(xxpc, rprefix, ruri);
+	  } else
+	    rb_raise(rb_eArgError, "Invalid argument type, only accept string, array of strings, or an array of arrays");
+	}
+      }
+      break;
+    default:
+      if (rb_obj_is_kind_of(argv[2], cXMLNS) == Qtrue) {
+	Data_Get_Struct(argv[2], ruby_xml_ns, rxns);
+	rprefix = rb_str_new2((const char*)rxns->ns->prefix);
+	ruri = rb_str_new2((const char*)rxns->ns->href);
+	ruby_xml_xpath_context_register_namespace(xxpc, rprefix, ruri);
+      } else
+	rb_raise(rb_eArgError, "Invalid argument type, only accept string, array of strings, or an array of arrays");
+    }
+  }
+  comp = xmlXPathCompile((xmlChar*)StringValuePtr(xpath_expr));
+
+  if (comp == NULL) {
+    xmlXPathFreeCompExpr(comp);
+    rb_raise(eXMLXPathInvalidPath, "Invalid XPath expression");
+  }
+  rxxp->xpop = xmlXPathCompiledEval(comp, rxxpc->ctxt);
+  xmlXPathFreeCompExpr(comp);
+
+  if (rxxpc->ctxt->namespaces != NULL)
+    xmlFree(rxxpc->ctxt->namespaces);
+
+  if (rxxp->xpop == NULL)
+    rb_raise(eXMLXPathInvalidPath,
+	     "Invalid XPath expression for this document");
+
+  if (rxxp->xpop->type != XPATH_NODESET)
+    return(Qnil);
+
+  return(ruby_xml_node_set_new2(node->xd, xpath,
+				rxxp->xpop->nodesetval));
+#else
+  rb_warn("libxml was compiled without XPath support");
+  return(Qfalse);
+#endif
+}
+
+
+VALUE
+ruby_xml_xpath_find2(int argc, VALUE *argv) {
+  return(ruby_xml_xpath_find(argc, argv, cXMLXPath));
+}
+
+
+void
+ruby_xml_xpath_free(ruby_xml_xpath *rxxp) {
+  if (rxxp->xpop != NULL) {
+    xmlXPathFreeObject(rxxp->xpop);
+    rxxp->xpop = NULL;
+  }
+
+  free(rxxp);
+}
+
+
+void
+ruby_xml_xpath_mark(ruby_xml_xpath *rxxp) {
+  if (rxxp == NULL) return;
+  if (!NIL_P(rxxp->ctxt)) rb_gc_mark(rxxp->ctxt);
+  if (!NIL_P(rxxp->xd)) rb_gc_mark(rxxp->xd);
+}
+
+
+VALUE
+ruby_xml_xpath_new(VALUE class, VALUE xd, VALUE ctxt,
+			 xmlXPathObjectPtr xpop) {
+  ruby_xml_xpath *rxxp;
+
+  rxxp = ALLOC(ruby_xml_xpath);
+  rxxp->ctxt = ctxt;
+  rxxp->xd = xd;
+  rxxp->xpop = xpop;
+  return(Data_Wrap_Struct(class, ruby_xml_xpath_mark,
+			  ruby_xml_xpath_free, rxxp));
+}
+
+
+/*
+ * call-seq:
+ *    xpath.set => nodeset
+ * 
+ * Obtain an XML::Node::Set with nodes matching this xpath.
+ */
+VALUE
+ruby_xml_xpath_set(VALUE self) {
+  ruby_xml_xpath *rxxp;
+  Data_Get_Struct(self, ruby_xml_xpath, rxxp);
+
+  if (rxxp->xpop == NULL || rxxp->xpop->type != XPATH_NODESET)
+    return(Qnil);
+
+  return(ruby_xml_node_set_new(cXMLNodeSet, rxxp->xd, self,
+			       rxxp->xpop->nodesetval));
+}
+
+
+/*
+ * call-seq:
+ *    xpath.set_type => num
+ * 
+ * Obtains the type identifier of this xpath
+ * set.
+ */
+VALUE
+ruby_xml_xpath_set_type(VALUE self) {
+  ruby_xml_xpath *rxxp;
+  Data_Get_Struct(self, ruby_xml_xpath, rxxp);
+
+  return(INT2FIX(rxxp->xpop->type));
+}
+
+// TODO maybe 'string' should alias as 'to_s'?
+
+/*
+ * call-seq:
+ *    xpath.string => "xpath" 
+ * 
+ * Obtain a string representation of this xpath.
+ */
+VALUE
+ruby_xml_xpath_string(VALUE self) {
+  ruby_xml_xpath *rxxp;
+  Data_Get_Struct(self, ruby_xml_xpath, rxxp);
+
+  if (rxxp->xpop->stringval == NULL)
+    return(Qnil);
+  else
+    return(rb_str_new2((const char*)rxxp->xpop->stringval));
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_xpath(void) {
+  cXMLXPath = rb_define_class_under(mXML, "XPath", rb_cObject);
+  rb_include_module(cXMLNode, rb_const_get(rb_cObject, rb_intern("Enumerable")));
+
+  eXMLXPathInvalidPath = rb_define_class_under(cXMLXPath,
+					       "InvalidPath", rb_eException);
+
+  rb_define_const(cXMLXPath, "UNDEFINED", INT2NUM(XPATH_UNDEFINED));
+  rb_define_const(cXMLXPath, "NODESET", INT2NUM(XPATH_NODESET));
+  rb_define_const(cXMLXPath, "BOOLEAN", INT2NUM(XPATH_BOOLEAN));
+  rb_define_const(cXMLXPath, "NUMBER", INT2NUM(XPATH_NUMBER));
+  rb_define_const(cXMLXPath, "STRING", INT2NUM(XPATH_STRING));
+  rb_define_const(cXMLXPath, "POINT", INT2NUM(XPATH_POINT));
+  rb_define_const(cXMLXPath, "RANGE", INT2NUM(XPATH_RANGE));
+  rb_define_const(cXMLXPath, "LOCATIONSET", INT2NUM(XPATH_LOCATIONSET));
+  rb_define_const(cXMLXPath, "USERS", INT2NUM(XPATH_USERS));
+  rb_define_const(cXMLXPath, "XSLT_TREE", INT2NUM(XPATH_XSLT_TREE));
+
+  rb_define_singleton_method(cXMLXPath, "find", ruby_xml_xpath_find, 2);
+
+  rb_define_method(cXMLXPath, "debug", ruby_xml_xpath_debug, 0);
+  rb_define_method(cXMLXPath, "each", ruby_xml_xpath_each, 0);
+  rb_define_method(cXMLXPath, "set", ruby_xml_xpath_set, 0);
+  rb_define_method(cXMLXPath, "set_type", ruby_xml_xpath_set_type, 0);
+  rb_define_method(cXMLXPath, "string", ruby_xml_xpath_string, 0);
+}
+
+#endif /* ifdef LIBXML_XPATH_ENABLED */

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xpath.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xpath.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xpath.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,24 @@
+/* $Id: ruby_xml_xpath.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_XPATH__
+#define __RUBY_XML_XPATH__
+
+extern VALUE cXMLXPath;
+extern VALUE eXMLXPathInvalidPath;
+
+typedef struct ruby_xml_xpath {
+  VALUE xd;
+  VALUE ctxt;
+  xmlXPathObjectPtr xpop;
+} ruby_xml_xpath;
+
+void ruby_xml_xpath_free(ruby_xml_xpath *rxxp);
+VALUE ruby_xml_xpath_find(int argc, VALUE *argv, VALUE class);
+VALUE ruby_xml_xpath_find2(int argc, VALUE *argv);
+VALUE ruby_xml_xpath_new(VALUE class, VALUE xd, VALUE xxpc,
+			 xmlXPathObjectPtr xpop);
+void ruby_init_xml_xpath(void);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xpath_context.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xpath_context.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xpath_context.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,125 @@
+/* $Id: ruby_xml_xpath_context.c,v 1.2 2006/02/27 12:55:32 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_xpath_context.h"
+
+VALUE cXMLXPathContext;
+
+/*
+ * call-seq:
+ *    context.doc => document
+ * 
+ * Obtain the XML::Document associated with this XPath.
+ */
+VALUE
+ruby_xml_xpath_context_doc_get(VALUE self) {
+  ruby_xml_xpath_context *rxxpc;
+  Data_Get_Struct(self, ruby_xml_xpath_context, rxxpc);
+
+  return(rxxpc->xd);
+}
+
+
+void
+ruby_xml_xpath_context_free(ruby_xml_xpath_context *rxxpc) {
+  if (rxxpc->ctxt != NULL) {
+    xmlXPathFreeContext(rxxpc->ctxt);
+    rxxpc->ctxt = NULL;
+  }
+
+  free(rxxpc);
+}
+
+
+void
+ruby_xml_xpath_context_mark(ruby_xml_xpath_context *rxxpc) {
+  if (rxxpc == NULL) return;
+  if (!NIL_P(rxxpc->xd)) rb_gc_mark(rxxpc->xd);
+}
+
+
+VALUE
+ruby_xml_xpath_context_new(VALUE class, VALUE xd,
+				 xmlXPathContextPtr xxpc) {
+  ruby_xml_xpath_context *rxxpc;
+
+  rxxpc = ALLOC(ruby_xml_xpath_context);
+  rxxpc->ctxt = xxpc;
+  rxxpc->xd = xd;
+  return(Data_Wrap_Struct(class, ruby_xml_xpath_context_mark,
+			  ruby_xml_xpath_context_free, rxxpc));
+}
+
+
+VALUE
+ruby_xml_xpath_context_new2(VALUE xd, xmlXPathContextPtr xxpc) {
+  return(ruby_xml_xpath_context_new(cXMLXPathContext, xd, xxpc));
+}
+
+
+VALUE
+ruby_xml_xpath_context_new3(VALUE xd) {
+  ruby_xml_document *rxd;
+  xmlXPathContextPtr ctxt;
+
+  Data_Get_Struct(xd, ruby_xml_document, rxd);
+  if (rxd->doc == NULL)
+    return(Qnil);
+
+  ctxt = xmlXPathNewContext(rxd->doc);
+  if (ctxt == NULL)
+    return(Qnil);
+
+  return(ruby_xml_xpath_context_new2(xd, ctxt));
+}
+
+
+VALUE
+ruby_xml_xpath_context_new4(VALUE rnode) {
+  ruby_xml_node *node;
+
+  Data_Get_Struct(rnode, ruby_xml_node, node);
+  return(ruby_xml_xpath_context_new3(node->xd));
+}
+
+
+/*
+ * call-seq:
+ *    context.register_namespace(prefix, uri) => (true|false)
+ * 
+ * Register the specified namespace URI with the specified prefix
+ * in this context.
+ */
+VALUE
+ruby_xml_xpath_context_register_namespace(VALUE self, VALUE prefix, VALUE uri) {
+  ruby_xml_xpath_context *rxxpc;
+
+  Data_Get_Struct(self, ruby_xml_xpath_context, rxxpc);
+  if (xmlXPathRegisterNs(rxxpc->ctxt, 
+                         (xmlChar*)StringValuePtr(prefix), 
+                         (xmlChar*)StringValuePtr(uri)) 
+                         == 0) {
+    return(Qtrue);
+  } else {
+    /* Should raise an exception, IMHO */
+    return(Qfalse);
+  }
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+  cXMLXPath = rb_define_class_under(mXML, "XPath", rb_cObject);
+#endif
+
+void
+ruby_init_xml_xpath_context(void) {
+  cXMLXPathContext = rb_define_class_under(cXMLXPath, "Context", rb_cObject);
+
+  rb_define_method(cXMLXPathContext, "register_namespace",
+		   ruby_xml_xpath_context_register_namespace, 2);
+  rb_define_method(cXMLXPathContext, "doc",
+		   ruby_xml_xpath_context_doc_get, 0);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xpath_context.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xpath_context.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xpath_context.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,24 @@
+/* $Id: ruby_xml_xpath_context.h,v 1.2 2006/02/27 12:55:32 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_XPATH_CONTEXT__
+#define __RUBY_XML_XPATH_CONTEXT__
+
+extern VALUE cXMLXPathContext;
+
+typedef struct ruby_xml_xpath_context {
+  VALUE xd;
+  xmlXPathContextPtr ctxt;
+} ruby_xml_xpath_context;
+
+void ruby_xml_xpath_context_free(ruby_xml_xpath_context *rxxpc);
+VALUE ruby_xml_xpath_context_new(VALUE class, VALUE xd,
+				 xmlXPathContextPtr ctxt);
+VALUE ruby_xml_xpath_context_new2(VALUE xd, xmlXPathContextPtr ctxt);
+VALUE ruby_xml_xpath_context_new3(VALUE xd);
+VALUE ruby_xml_xpath_context_new4(VALUE rnode);
+VALUE ruby_xml_xpath_context_register_namespace(VALUE self, VALUE prefix, VALUE uri);
+void ruby_init_xml_xpath_context(void);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xpointer.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xpointer.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xpointer.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,100 @@
+/* $Id: ruby_xml_xpointer.c,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_xpointer.h"
+
+VALUE cXMLXPointer;
+VALUE eXMLXPointerInvalidExpression;
+
+VALUE
+ruby_xml_xpointer_point(VALUE class, VALUE rnode, VALUE xptr_str) {
+#ifdef LIBXML_XPTR_ENABLED
+  ruby_xml_node *node;
+  ruby_xml_xpath_context *xxpc;
+  VALUE rxptr_xpth_ctxt, rxxp;
+  xmlXPathObjectPtr xpath;
+
+  Check_Type(xptr_str, T_STRING);
+  if (rb_obj_is_kind_of(rnode, cXMLNode) == Qfalse)
+    rb_raise(rb_eTypeError, "require an XML::Node object");
+
+  Data_Get_Struct(rnode, ruby_xml_node, node);
+
+  rxptr_xpth_ctxt = ruby_xml_xpath_context_new(cXMLXPathContext, node->xd,
+					       xmlXPtrNewContext(node->node->doc, node->node, NULL));
+  if (NIL_P(rxptr_xpth_ctxt))
+    return(Qnil);
+  Data_Get_Struct(rxptr_xpth_ctxt, ruby_xml_xpath_context, xxpc);
+
+  xpath = xmlXPtrEval((xmlChar*)StringValuePtr(xptr_str), xxpc->ctxt);
+  if (xpath == NULL)
+    rb_raise(eXMLXPointerInvalidExpression, "invalid xpointer expression");
+
+  rxxp = ruby_xml_xpath_new(cXMLXPath, node->xd, rxptr_xpth_ctxt, xpath);
+  return(rxxp);
+#else
+  rb_warn("libxml was compiled without XPointer support");
+  return(Qfalse);
+#endif
+}
+
+
+VALUE
+ruby_xml_xpointer_point2(VALUE node, VALUE xptr_str) {
+  return(ruby_xml_xpointer_point(cXMLXPointer, node, xptr_str));
+}
+
+
+/*
+ * call-seq:
+ *    XML::XPointer.range(start_node, end_node) => xpath
+ * 
+ * Create an xpath representing the range between the supplied
+ * start and end node.
+ */
+VALUE
+ruby_xml_xpointer_range(VALUE class, VALUE rstart, VALUE rend) {
+#ifdef LIBXML_XPTR_ENABLED
+  ruby_xml_node *start, *end;
+  VALUE rxxp;
+  xmlXPathObjectPtr xpath;
+
+  if (rb_obj_is_kind_of(rstart, cXMLNode) == Qfalse)
+    rb_raise(rb_eTypeError, "require an XML::Node object as a starting point");
+  if (rb_obj_is_kind_of(rend, cXMLNode) == Qfalse)
+    rb_raise(rb_eTypeError, "require an XML::Node object as an ending point");
+
+  Data_Get_Struct(rstart, ruby_xml_node, start);
+  if (start->node == NULL)
+    return(Qnil);
+
+  Data_Get_Struct(rend, ruby_xml_node, end);
+  if (end->node == NULL)
+    return(Qnil);
+
+  xpath = xmlXPtrNewRangeNodes(start->node, end->node);
+  if (xpath == NULL)
+    rb_fatal("You shouldn't be able to have this happen");
+
+  rxxp = ruby_xml_xpath_new(cXMLXPath, start->xd, Qnil, xpath);
+  return(rxxp);
+#else
+  rb_warn("libxml was compiled without XPointer support");
+  return(Qfalse);
+#endif
+}
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+#endif
+
+void
+ruby_init_xml_xpointer(void) {
+  cXMLXPointer = rb_define_class_under(mXML, "XPointer", rb_cObject);
+  eXMLXPointerInvalidExpression = rb_define_class_under(cXMLXPointer, "InvalidExpression", rb_eException);
+
+  rb_define_singleton_method(cXMLXPointer, "range", ruby_xml_xpointer_range, 2);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xpointer.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xpointer.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xpointer.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,27 @@
+/* $Id: ruby_xml_xpointer.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_XPOINTER__
+#define __RUBY_XML_XPOINTER__
+
+extern VALUE cXMLXPointer;
+extern VALUE eXMLXPointerInvalidExpression;
+
+typedef struct ruby_xml_xpointer {
+  VALUE xd;
+  VALUE ctxt;
+  /*
+   * This needs to go into a xpointer data struct:
+   *
+   * xmlLocationSetPtr xptr;
+   *
+   * I also need an xpointer data struct type.
+  */
+} ruby_xml_xpointer;
+
+VALUE ruby_xml_xpointer_point(VALUE class, VALUE node, VALUE xptr_string);
+VALUE ruby_xml_xpointer_point2(VALUE node, VALUE xptr_string);
+void ruby_init_xml_xpointer(void);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xpointer_context.c
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xpointer_context.c	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xpointer_context.c	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,21 @@
+/* $Id: ruby_xml_xpointer_context.c,v 1.2 2006/02/27 12:55:32 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#include "libxml.h"
+#include "ruby_xml_xpointer_context.h"
+
+VALUE cXMLXPointerContext;
+VALUE eXMLXPointerContextInvalidPath;
+
+// Rdoc needs to know 
+#ifdef RDOC_NEVER_DEFINED
+  mXML = rb_define_module("XML");
+  cXMLXPointer = rb_define_class_under(mXML, "XPointer", rb_cObject);
+#endif
+
+void
+ruby_init_xml_xpointer_context(void) {
+  cXMLXPointerContext = rb_define_class_under(cXMLXPointer, "Context", cXMLXPathContext);
+  eXMLXPointerContextInvalidPath = rb_define_class_under(cXMLXPointerContext, "InvalidPath", rb_eException);
+}

Added: packages-wip/libxml-ruby/trunk/ruby_xml_xpointer_context.h
===================================================================
--- packages-wip/libxml-ruby/trunk/ruby_xml_xpointer_context.h	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/ruby_xml_xpointer_context.h	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,18 @@
+/* $Id: ruby_xml_xpointer_context.h,v 1.1 2006/02/21 20:40:16 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+#ifndef __RUBY_XML_XPOINTER_CONTEXT__
+#define __RUBY_XML_XPOINTER_CONTEXT__
+
+extern VALUE cXMLXPointerContext;
+extern VALUE eXMLXPointerContextInvalidPath;
+
+typedef struct ruby_xml_xpointer_context {
+  VALUE xd;
+  xmlXPathContextPtr ctxt;
+} ruby_xml_xpointer_context;
+
+void ruby_init_xml_xpointer_context(void);
+
+#endif

Added: packages-wip/libxml-ruby/trunk/sax_parser_callbacks.inc
===================================================================
--- packages-wip/libxml-ruby/trunk/sax_parser_callbacks.inc	2006-11-03 21:03:21 UTC (rev 963)
+++ packages-wip/libxml-ruby/trunk/sax_parser_callbacks.inc	2006-11-03 21:04:08 UTC (rev 964)
@@ -0,0 +1,202 @@
+/* $Id: sax_parser_callbacks.inc,v 1.1 2006/04/14 14:50:58 roscopeco Exp $ */
+
+/* Please see the LICENSE file for copyright and distribution information */
+
+/*
+ * SAX CALLBACK HANDLERS
+ */ 
+static void internal_subset_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *name,
+       const char *extid,
+       const char *sysid) {
+  VALUE handler = cbp->internalSubset;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler, callsym, 3, rb_str_new2(name),
+        rb_str_new2(extid), rb_str_new2(sysid));
+  }    
+}
+
+static void is_standalone_func(ruby_xml_sax_parser_callbacks *cbp) {
+  VALUE handler = cbp->isStandalone;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,0);
+  }    
+}
+
+static void has_internal_subset_func(ruby_xml_sax_parser_callbacks *cbp) {
+  VALUE handler = cbp->hasInternalSubset;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,0);
+  }    
+}
+
+static void has_external_subset_func(ruby_xml_sax_parser_callbacks *cbp) {
+  VALUE handler = cbp->hasExternalSubset;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,0);
+  }    
+}
+
+static void start_document_func(ruby_xml_sax_parser_callbacks *cbp) {
+  VALUE handler = cbp->startDocument;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,0);
+  }    
+}
+
+static void end_document_func(ruby_xml_sax_parser_callbacks *cbp) {
+  VALUE handler = cbp->endDocument;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,0);
+  }    
+}
+
+static void start_element_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *name, const char **attrs) {  
+  VALUE handler = cbp->startElement;
+  VALUE ahsh = rb_hash_new();
+  const char *attr, *value;
+  
+  if (attrs) {
+    while ((attr = *(attrs++))) {
+      value = *(attrs++);            
+      rb_hash_aset(ahsh, rb_str_new2(attr), rb_str_new2(value));
+    }
+  }    
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,2,rb_str_new2(name),ahsh);
+  }    
+}        
+
+static void end_element_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *name) {
+  VALUE handler = cbp->endElement;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,1,rb_str_new2(name));
+  }    
+}
+
+static void reference_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *name) {
+  VALUE handler = cbp->reference;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,1,rb_str_new2(name));
+  }    
+}
+
+static void characters_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *chars, int len) {
+  VALUE handler = cbp->characters;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,1,rb_str_new(chars, len));
+  }    
+}
+
+static void processing_instruction_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *target, const char *data) {
+  VALUE handler = cbp->processingInstruction;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler, callsym, 2,
+        rb_str_new2(target),rb_str_new2(data));
+  }    
+}
+
+static void comment_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *msg) {
+  VALUE handler = cbp->comment;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,1,rb_str_new2(msg));
+  }    
+}
+
+// TODO these next three should actually be formatting messages.
+static void warning_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *msg, ...) {
+  VALUE handler = cbp->xmlParserWarning;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,1,rb_str_new2(msg));
+  }    
+}
+
+static void error_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *msg, ...) {
+  VALUE handler = cbp->xmlParserError;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,1,rb_str_new2(msg));
+  }    
+}
+
+static void fatal_error_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *msg, ...) {
+  VALUE handler = cbp->xmlParserFatalError;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,1,rb_str_new2(msg));
+  }    
+}
+
+static void cdata_block_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *value, int len) {
+  VALUE handler = cbp->cdataBlock;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler,callsym,1,rb_str_new(value, len));
+  }    
+}
+
+static void external_subset_func(ruby_xml_sax_parser_callbacks *cbp, 
+       const char *name,
+       const char *extid,
+       const char *sysid) {
+  VALUE handler = cbp->externalSubset;
+  
+  if (handler && handler != Qnil) {
+    rb_funcall(handler, callsym, 3, rb_str_new2(name),
+        rb_str_new2(extid), rb_str_new2(sysid));
+  }    
+}
+
+static xmlSAXHandler rubySAXHandlerStruct = {
+  (internalSubsetSAXFunc)internal_subset_func,
+  (isStandaloneSAXFunc)is_standalone_func,
+  (hasInternalSubsetSAXFunc)has_internal_subset_func,
+  (hasExternalSubsetSAXFunc)has_external_subset_func,
+  0, /* resolveEntity */
+  0, /* getEntity */
+  0, /* entityDecl */
+  0, /* notationDecl */
+  0, /* attributeDecl */
+  0, /* elementDecl */
+  0, /* unparsedEntityDecl */
+  0, /* setDocumentLocator */
+  (startDocumentSAXFunc)start_document_func, 
+  (endDocumentSAXFunc)end_document_func, 
+  (startElementSAXFunc)start_element_func, 
+  (endElementSAXFunc)end_element_func, 
+  (referenceSAXFunc)reference_func,
+  (charactersSAXFunc)characters_func,
+  0, /* ignorableWhitespace */
+  (processingInstructionSAXFunc)processing_instruction_func,
+  (commentSAXFunc)comment_func,
+  (warningSAXFunc)warning_func,
+  (errorSAXFunc)error_func,
+  (fatalErrorSAXFunc)fatal_error_func,
+  0, /* xmlGetParameterEntity */
+  (cdataBlockSAXFunc)cdata_block_func,
+  (externalSubsetSAXFunc)external_subset_func,
+  1
+};




More information about the pkg-ruby-extras-maintainers mailing list