/* call-seq: * doc.canonicalize(mode=XML_C14N_1_0,inclusive_namespaces=nil,with_comments=false) * doc.canonicalize { |obj, parent| ... } * * Canonicalize a document and return the results. Takes an optional block * that takes two parameters: the +obj+ and that node's +parent+. * The +obj+ will be either a Nokogiri::XML::Node, or a Nokogiri::XML::Namespace * The block must return a non-nil, non-false value if the +obj+ passed in * should be included in the canonicalized document. */ static VALUE canonicalize(int argc, VALUE* argv, VALUE self) { VALUE mode; VALUE incl_ns; VALUE with_comments; xmlChar **ns; long ns_len, i; xmlDocPtr doc; xmlOutputBufferPtr buf; xmlC14NIsVisibleCallback cb = NULL; void * ctx = NULL; VALUE rb_cStringIO; VALUE io; rb_scan_args(argc, argv, "03", &mode, &incl_ns, &with_comments); Data_Get_Struct(self, xmlDoc, doc); rb_cStringIO = rb_const_get_at(rb_cObject, rb_intern("StringIO")); io = rb_class_new_instance(0, 0, rb_cStringIO); buf = xmlAllocOutputBuffer(NULL); buf->writecallback = (xmlOutputWriteCallback)io_write_callback; buf->closecallback = (xmlOutputCloseCallback)io_close_callback; buf->context = (void *)io; if(rb_block_given_p()) { cb = block_caller; ctx = (void *)rb_block_proc(); } if(NIL_P(incl_ns)){ ns = NULL; } else{ ns_len = RARRAY_LEN(incl_ns); ns = calloc((size_t)ns_len+1, sizeof(xmlChar *)); for (i = 0 ; i < ns_len ; i++) { VALUE entry = rb_ary_entry(incl_ns, i); const char * ptr = StringValuePtr(entry); ns[i] = (xmlChar*) ptr; } } xmlC14NExecute(doc, cb, ctx, (int) (NIL_P(mode) ? 0 : NUM2INT(mode)), ns, (int) (NIL_P(with_comments) ? 0 : 1), buf); xmlOutputBufferClose(buf); return rb_funcall(io, rb_intern("string"), 0); }