class Ox::Builder
An XML builder.
Public Class Methods
Source
static VALUE builder_file(int argc, VALUE *argv, VALUE self) {
Builder b = ALLOC(struct _builder);
int indent = ox_default_options.indent;
long buf_size = 0;
FILE *f;
if (1 > argc) {
rb_raise(ox_arg_error_class, "missing filename");
}
Check_Type(*argv, T_STRING);
if (NULL == (f = fopen(StringValuePtr(*argv), "w"))) {
xfree(b);
rb_raise(rb_eIOError, "%s\n", strerror(errno));
}
if (2 == argc) {
volatile VALUE v;
rb_check_type(argv[1], T_HASH);
if (Qnil != (v = rb_hash_lookup(argv[1], ox_indent_sym))) {
if (rb_cInteger != rb_obj_class(v)) {
rb_raise(ox_parse_error_class, ":indent must be a fixnum.\n");
}
indent = NUM2INT(v);
}
if (Qnil != (v = rb_hash_lookup(argv[1], ox_size_sym))) {
if (rb_cInteger != rb_obj_class(v)) {
rb_raise(ox_parse_error_class, ":size must be a fixnum.\n");
}
buf_size = NUM2LONG(v);
}
}
b->file = f;
init(b, fileno(f), indent, buf_size);
if (rb_block_given_p()) {
volatile VALUE rb = Data_Wrap_Struct(builder_class, NULL, builder_free, b);
rb_yield(rb);
bclose(b);
return Qnil;
} else {
return Data_Wrap_Struct(builder_class, NULL, builder_free, b);
}
}
Creates a new Builder that will write to a file.
-
filename(String) filename to write to -
options- (Hash) formating options-
:indent(Fixnum) indentaion level, negative values excludes terminating newline -
:size(Fixnum) the initial size of the string buffer
-
Source
static VALUE builder_io(int argc, VALUE *argv, VALUE self) {
Builder b = ALLOC(struct _builder);
int indent = ox_default_options.indent;
long buf_size = 0;
int fd;
volatile VALUE v;
if (1 > argc) {
rb_raise(ox_arg_error_class, "missing IO object");
}
if (!rb_respond_to(*argv, ox_fileno_id) || Qnil == (v = rb_funcall(*argv, ox_fileno_id, 0)) ||
0 == (fd = FIX2INT(v))) {
rb_raise(rb_eIOError, "expected an IO that has a fileno.");
}
if (2 == argc) {
volatile VALUE v;
rb_check_type(argv[1], T_HASH);
if (Qnil != (v = rb_hash_lookup(argv[1], ox_indent_sym))) {
if (rb_cInteger != rb_obj_class(v)) {
rb_raise(ox_parse_error_class, ":indent must be a fixnum.\n");
}
indent = NUM2INT(v);
}
if (Qnil != (v = rb_hash_lookup(argv[1], ox_size_sym))) {
if (rb_cInteger != rb_obj_class(v)) {
rb_raise(ox_parse_error_class, ":size must be a fixnum.\n");
}
buf_size = NUM2LONG(v);
}
}
b->file = NULL;
init(b, fd, indent, buf_size);
if (rb_block_given_p()) {
volatile VALUE rb = Data_Wrap_Struct(builder_class, NULL, builder_free, b);
rb_yield(rb);
bclose(b);
return Qnil;
} else {
return Data_Wrap_Struct(builder_class, NULL, builder_free, b);
}
}
Creates a new Builder that will write to an IO instance.
-
io(String) IO to write to -
options- (Hash) formating options-
:indent(Fixnum) indentaion level, negative values excludes terminating newline -
:size(Fixnum) the initial size of the string buffer
-
Source
static VALUE builder_new(int argc, VALUE *argv, VALUE self) {
Builder b = ALLOC(struct _builder);
int indent = ox_default_options.indent;
long buf_size = 0;
if (1 == argc) {
volatile VALUE v;
rb_check_type(*argv, T_HASH);
if (Qnil != (v = rb_hash_lookup(*argv, ox_indent_sym))) {
if (rb_cInteger != rb_obj_class(v)) {
rb_raise(ox_parse_error_class, ":indent must be a fixnum.\n");
}
indent = NUM2INT(v);
}
if (Qnil != (v = rb_hash_lookup(*argv, ox_size_sym))) {
if (rb_cInteger != rb_obj_class(v)) {
rb_raise(ox_parse_error_class, ":size must be a fixnum.\n");
}
buf_size = NUM2LONG(v);
}
}
b->file = NULL;
init(b, 0, indent, buf_size);
if (rb_block_given_p()) {
volatile VALUE rb = Data_Wrap_Struct(builder_class, NULL, builder_free, b);
rb_yield(rb);
bclose(b);
return to_s(b);
} else {
return Data_Wrap_Struct(builder_class, NULL, builder_free, b);
}
}
Creates a new Builder that will write to a string that can be retrieved with the to_s() method. If a block is given it is executed with a single parameter which is the builder instance. The return value is then the generated string.
-
options- (Hash) formating options-
:indent(Fixnum) indentaion level, negative values excludes terminating newline -
:size(Fixnum) the initial size of the string buffer
-
Public Instance Methods
Source
static VALUE builder_cdata(VALUE self, VALUE data) {
Builder b = (Builder)DATA_PTR(self);
volatile VALUE v = data;
const char *str;
const char *s;
const char *end;
int len;
v = rb_String(v);
str = StringValuePtr(v);
len = (int)RSTRING_LEN(v);
s = str;
end = str + len;
i_am_a_child(b, false);
append_indent(b);
buf_append_string(&b->buf, "<![CDATA[", 9);
b->col += 9;
b->pos += 9;
buf_append_string(&b->buf, str, len);
b->col += len;
s = strchr(s, '\n');
while (NULL != s) {
b->line++;
b->col = end - s;
s = strchr(s + 1, '\n');
}
b->pos += len;
buf_append_string(&b->buf, "]]>", 3);
b->col += 3;
b->pos += 3;
return Qnil;
}
Adds a CDATA element to the XML string being formed.
-
data- (String) contents of the CDATA element
Source
static VALUE builder_close(VALUE self) {
bclose((Builder)DATA_PTR(self));
return Qnil;
}
Closes the all elements and the document.
Source
static VALUE builder_column(VALUE self) {
return LONG2NUM(((Builder)DATA_PTR(self))->col);
}
Returns the current column in the output. The first character in a line is at column 1.
Source
static VALUE builder_comment(VALUE self, VALUE text) {
Builder b = (Builder)DATA_PTR(self);
rb_check_type(text, T_STRING);
i_am_a_child(b, false);
append_indent(b);
buf_append_string(&b->buf, "<!--", 4);
b->col += 5;
b->pos += 5;
append_string(b, StringValuePtr(text), RSTRING_LEN(text), xml_element_chars, false);
buf_append_string(&b->buf, "-->", 3);
b->col += 5;
b->pos += 5;
return Qnil;
}
Adds a comment element to the XML string being formed.
-
text- (String) contents of the comment
Source
static VALUE builder_doctype(VALUE self, VALUE text) {
Builder b = (Builder)DATA_PTR(self);
rb_check_type(text, T_STRING);
i_am_a_child(b, false);
append_indent(b);
buf_append_string(&b->buf, "<!DOCTYPE ", 10);
b->col += 10;
b->pos += 10;
append_string(b, StringValuePtr(text), RSTRING_LEN(text), xml_element_chars, false);
buf_append(&b->buf, '>');
b->col++;
b->pos++;
return Qnil;
}
Adds a DOCTYPE element to the XML string being formed.
-
text- (String) contents of the doctype
Source
static VALUE builder_element(int argc, VALUE *argv, VALUE self) {
Builder b = (Builder)DATA_PTR(self);
Element e;
const char *name;
long len;
if (1 > argc) {
rb_raise(ox_arg_error_class, "missing element name");
}
i_am_a_child(b, false);
append_indent(b);
b->depth++;
if (MAX_DEPTH <= b->depth) {
rb_raise(ox_arg_error_class, "XML too deeply nested");
}
switch (rb_type(*argv)) {
case T_STRING:
name = StringValuePtr(*argv);
len = RSTRING_LEN(*argv);
break;
case T_SYMBOL:
name = rb_id2name(SYM2ID(*argv));
len = strlen(name);
break;
default: rb_raise(ox_arg_error_class, "expected a Symbol or String for an element name"); break;
}
e = &b->stack[b->depth];
if (sizeof(e->buf) <= (size_t)len) {
e->name = strdup(name);
*e->buf = '\0';
} else {
strcpy(e->buf, name);
e->name = e->buf;
}
e->len = len;
e->has_child = false;
e->non_text_child = false;
buf_append(&b->buf, '<');
b->col++;
b->pos++;
append_string(b, e->name, len, xml_element_chars, false);
if (1 < argc && T_HASH == rb_type(argv[1])) {
rb_hash_foreach(argv[1], append_attr, (VALUE)b);
}
// Do not close with > or /> yet. That is done with i_am_a_child() or pop().
if (rb_block_given_p()) {
rb_yield(self);
pop(b);
}
return Qnil;
}
Adds an element with the name and attributes provided. If a block is given then on closing of the block a pop() is called.
-
name- (String) name of the element -
attributes- (Hash) of the element
Source
static VALUE builder_get_indent(VALUE self) {
return INT2NUM(((Builder)DATA_PTR(self))->indent);
}
Returns the indentation level
Source
static VALUE builder_set_indent(VALUE self, VALUE indent) {
if (rb_cInteger != rb_obj_class(indent)) {
rb_raise(ox_parse_error_class, "indent must be a fixnum.\n");
}
((Builder)DATA_PTR(self))->indent = NUM2INT(indent);
return Qnil;
}
Sets the indentation level
-
indent(Fixnum) indentaion level, negative values excludes terminating newline
Source
static VALUE builder_instruct(int argc, VALUE *argv, VALUE self) {
Builder b = (Builder)DATA_PTR(self);
i_am_a_child(b, false);
append_indent(b);
if (0 == argc) {
buf_append_string(&b->buf, "<?xml?>", 7);
b->col += 7;
b->pos += 7;
} else {
volatile VALUE v;
buf_append_string(&b->buf, "<?", 2);
b->col += 2;
b->pos += 2;
append_sym_str(b, *argv);
if (1 < argc && rb_cHash == rb_obj_class(argv[1])) {
int len;
if (Qnil != (v = rb_hash_lookup(argv[1], ox_version_sym))) {
if (rb_cString != rb_obj_class(v)) {
rb_raise(ox_parse_error_class, ":version must be a Symbol.\n");
}
len = (int)RSTRING_LEN(v);
buf_append_string(&b->buf, " version=\"", 10);
buf_append_string(&b->buf, StringValuePtr(v), len);
buf_append(&b->buf, '"');
b->col += len + 11;
b->pos += len + 11;
}
if (Qnil != (v = rb_hash_lookup(argv[1], ox_encoding_sym))) {
if (rb_cString != rb_obj_class(v)) {
rb_raise(ox_parse_error_class, ":encoding must be a Symbol.\n");
}
len = (int)RSTRING_LEN(v);
buf_append_string(&b->buf, " encoding=\"", 11);
buf_append_string(&b->buf, StringValuePtr(v), len);
buf_append(&b->buf, '"');
b->col += len + 12;
b->pos += len + 12;
strncpy(b->encoding, StringValuePtr(v), sizeof(b->encoding));
b->encoding[sizeof(b->encoding) - 1] = '\0';
}
if (Qnil != (v = rb_hash_lookup(argv[1], ox_standalone_sym))) {
if (rb_cString != rb_obj_class(v)) {
rb_raise(ox_parse_error_class, ":standalone must be a Symbol.\n");
}
len = (int)RSTRING_LEN(v);
buf_append_string(&b->buf, " standalone=\"", 13);
buf_append_string(&b->buf, StringValuePtr(v), len);
buf_append(&b->buf, '"');
b->col += len + 14;
b->pos += len + 14;
}
}
buf_append_string(&b->buf, "?>", 2);
b->col += 2;
b->pos += 2;
}
return Qnil;
}
Adds the top level <?xml?> element.
-
decl- (String) âxmlâ expected -
options- (Hash) version or encoding
Source
static VALUE builder_line(VALUE self) {
return LONG2NUM(((Builder)DATA_PTR(self))->line);
}
Returns the current line in the output. The first line is line 1.
Source
static VALUE builder_pop(VALUE self) {
pop((Builder)DATA_PTR(self));
return Qnil;
}
Closes the current element.
Source
static VALUE builder_pos(VALUE self) {
return LONG2NUM(((Builder)DATA_PTR(self))->pos);
}
Returns the number of bytes written.
Source
static VALUE builder_raw(VALUE self, VALUE text) {
Builder b = (Builder)DATA_PTR(self);
volatile VALUE v = text;
const char *str;
const char *s;
const char *end;
int len;
v = rb_String(v);
str = StringValuePtr(v);
len = (int)RSTRING_LEN(v);
s = str;
end = str + len;
i_am_a_child(b, true);
buf_append_string(&b->buf, str, len);
b->col += len;
s = strchr(s, '\n');
while (NULL != s) {
b->line++;
b->col = end - s;
s = strchr(s + 1, '\n');
}
b->pos += len;
return Qnil;
}
Adds the provided string directly to the XML without formatting or modifications.
-
text- (String) contents to be added
Source
static VALUE builder_text(int argc, VALUE *argv, VALUE self) {
Builder b = (Builder)DATA_PTR(self);
volatile VALUE v;
volatile VALUE strip_invalid_chars;
if ((0 == argc) || (argc > 2)) {
rb_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1..2)", argc);
}
v = argv[0];
if (2 == argc) {
strip_invalid_chars = argv[1];
} else {
strip_invalid_chars = Qfalse;
}
v = rb_String(v);
i_am_a_child(b, true);
append_string(b, StringValuePtr(v), RSTRING_LEN(v), xml_element_chars, RTEST(strip_invalid_chars));
return Qnil;
}
Adds a text element to the XML string being formed.
-
text- (String) contents of the text field -
strip_invalid_chars- [true|false] strips any characters invalid for XML, defaults to false
Source
static VALUE builder_to_s(VALUE self) {
return to_s((Builder)DATA_PTR(self));
}
Returns the JSON document string in what ever state the construction is at.
Source
static VALUE builder_void_element(int argc, VALUE *argv, VALUE self) {
Builder b = (Builder)DATA_PTR(self);
const char *name;
long len;
if (1 > argc) {
rb_raise(ox_arg_error_class, "missing element name");
}
i_am_a_child(b, false);
append_indent(b);
switch (rb_type(*argv)) {
case T_STRING:
name = StringValuePtr(*argv);
len = RSTRING_LEN(*argv);
break;
case T_SYMBOL:
name = rb_id2name(SYM2ID(*argv));
len = strlen(name);
break;
default: rb_raise(ox_arg_error_class, "expected a Symbol or String for an element name"); break;
}
buf_append(&b->buf, '<');
b->col++;
b->pos++;
append_string(b, name, len, xml_element_chars, false);
if (1 < argc && T_HASH == rb_type(argv[1])) {
rb_hash_foreach(argv[1], append_attr, (VALUE)b);
}
buf_append_string(&b->buf, ">", 1);
b->col++;
;
b->pos++;
return Qnil;
}
Adds an void element with the name and attributes provided.
-
name- (String) name of the element -
attributes- (Hash) of the element