File: ruby_xml_parser.c

package info (click to toggle)
ruby-libxml 2.7.0-3
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 2,024 kB
  • ctags: 2,251
  • sloc: xml: 9,628; ansic: 8,409; ruby: 7,806; makefile: 3
file content (94 lines) | stat: -rw-r--r-- 2,592 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* Please see the LICENSE file for copyright and distribution information */

#include <stdarg.h>
#include "ruby_libxml.h"

/*
 * Document-class: LibXML::XML::Parser
 *
 * The XML::Parser provides a tree based API for processing
 * xml documents, in contract to XML::Reader's stream
 * based api and XML::SaxParser callback based API.
 *
 * As a result, parsing a document creates an in-memory document object
 * that consist of any number of XML::Node instances.  This is simple
 * and powerful model, but has the major limitation that the size of
 * the document that can be processed is limited by the amount of
 * memory available.  In such cases, it is better to use the XML::Reader.
 *
 * Using the parser is simple:
 *
 *   parser = XML::Parser.file('my_file')
 *   doc = parser.parse
 *
 * You can also parse documents (see XML::Parser.document), 
 * strings (see XML::Parser.string) and io objects (see
 * XML::Parser.io).
 */

VALUE cXMLParser;
static ID CONTEXT_ATTR;

/*
 * call-seq:
 *    parser.initialize(context) -> XML::Parser
 *
 * Creates a new XML::Parser from the specified 
 * XML::Parser::Context.
 */
static VALUE rxml_parser_initialize(int argc, VALUE *argv, VALUE self)
{
  VALUE context = Qnil;

  rb_scan_args(argc, argv, "01", &context);

  if (context == Qnil)
  {
    rb_warn("Passing no parameters to XML::Parser.new is deprecated.  Pass an instance of XML::Parser::Context instead.");
    context = rb_class_new_instance(0, NULL, cXMLParserContext);
  }

  rb_ivar_set(self, CONTEXT_ATTR, context);
  return self;
}

/*
 * call-seq:
 *    parser.parse -> XML::Document
 *
 * Parse the input XML and create an XML::Document with
 * it's content. If an error occurs, XML::Parser::ParseError
 * is thrown.
 */
static VALUE rxml_parser_parse(VALUE self)
{
  xmlParserCtxtPtr ctxt;
  VALUE context = rb_ivar_get(self, CONTEXT_ATTR);
  
  Data_Get_Struct(context, xmlParserCtxt, ctxt);

  if ((xmlParseDocument(ctxt) == -1 || !ctxt->wellFormed) && ! ctxt->recovery)
  {
    if (ctxt->myDoc)
      xmlFreeDoc(ctxt->myDoc);
    rxml_raise(&ctxt->lastError);
  }

  rb_funcall(context, rb_intern("close"), 0);

  return rxml_document_wrap(ctxt->myDoc);
}

void rxml_init_parser(void)
{
  cXMLParser = rb_define_class_under(mXML, "Parser", rb_cObject);

  /* Atributes */
  CONTEXT_ATTR = rb_intern("@context");
  rb_define_attr(cXMLParser, "input", 1, 0);
  rb_define_attr(cXMLParser, "context", 1, 0);

  /* Instance Methods */
  rb_define_method(cXMLParser, "initialize", rxml_parser_initialize, -1);
  rb_define_method(cXMLParser, "parse", rxml_parser_parse, 0);
}