Skip to content

Commit

Permalink
changed line numbers in sax to be the start of elements
Browse files Browse the repository at this point in the history
  • Loading branch information
ohler55 committed Feb 28, 2013
1 parent f5c3c72 commit b39570b
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 69 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ A fast XML parser and Object marshaller as a Ruby gem.

## <a name="release">Release Notes</a>

### Release 1.9.1

- Fixed the line numbers to be the start of the elements in the sax parser.

### Release 1.9.0

- Added a new feature to Ox::Element.locate() that allows filtering by node Class.
Expand Down
32 changes: 20 additions & 12 deletions ext/ox/sax.c
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ read_children(SaxDrive dr, int first) {
col = dr->col;
err = ('\0' == read_name_token(dr));
dr->line = line;
dr->col = col - 2; // -2 for </
dr->col = col;
return err;
break;
case '\0':
Expand Down Expand Up @@ -686,6 +686,8 @@ read_instruction(SaxDrive dr) {
static int
read_doctype(SaxDrive dr) {
char c;
int line = dr->line;
int col = dr->col - 10;

dr->str = dr->cur - 1; /* mark the start */
while ('>' != (c = sax_drive_get(dr))) {
Expand All @@ -699,10 +701,10 @@ read_doctype(SaxDrive dr) {
VALUE args[1];

if (dr->has_line) {
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(dr->line));
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(line));
}
if (dr->has_column) {
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(dr->col));
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(col));
}
args[0] = rb_str_new2(dr->str);
rb_funcall2(dr->handler, ox_doctype_id, 1, args);
Expand All @@ -718,6 +720,8 @@ static int
read_cdata(SaxDrive dr) {
char c;
int end = 0;
int line = dr->line;
int col = dr->col - 10;

backup(dr); /* back up to the start in case the cdata is empty */
dr->str = dr->cur; /* mark the start */
Expand Down Expand Up @@ -752,10 +756,10 @@ read_cdata(SaxDrive dr) {
}
#endif
if (dr->has_line) {
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(dr->line));
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(line));
}
if (dr->has_column) {
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(dr->col));
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(col));
}
rb_funcall2(dr->handler, ox_cdata_id, 1, args);
}
Expand All @@ -770,6 +774,8 @@ static int
read_comment(SaxDrive dr) {
char c;
int end = 0;
int line = dr->line;
int col = dr->col - 5;

dr->str = dr->cur - 1; /* mark the start */
while (1) {
Expand Down Expand Up @@ -806,10 +812,10 @@ read_comment(SaxDrive dr) {
}
#endif
if (dr->has_line) {
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(dr->line));
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(line));
}
if (dr->has_column) {
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(dr->col));
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(col));
}
rb_funcall2(dr->handler, ox_comment_id, 1, args);
}
Expand Down Expand Up @@ -906,7 +912,7 @@ read_element(SaxDrive dr) {
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(line));
}
if (dr->has_column) {
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(col));
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(col - 2));
}
args[0] = name;
rb_funcall2(dr->handler, ox_end_element_id, 1, args);
Expand All @@ -920,6 +926,8 @@ read_element(SaxDrive dr) {
static int
read_text(SaxDrive dr) {
char c;
int line = dr->line;
int col = dr->col - 1;

/* start marked in read_children */
/*dr->str = dr->cur - 1; / * mark the start */
Expand All @@ -934,10 +942,10 @@ read_text(SaxDrive dr) {
VALUE args[1];

if (dr->has_line) {
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(dr->line));
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(line));
}
if (dr->has_column) {
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(dr->col));
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(col));
}
*args = dr->value_obj;
rb_funcall2(dr->handler, ox_value_id, 1, args);
Expand All @@ -960,10 +968,10 @@ read_text(SaxDrive dr) {
}
#endif
if (dr->has_line) {
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(dr->line));
rb_ivar_set(dr->handler, ox_at_line_id, INT2FIX(line));
}
if (dr->has_column) {
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(dr->col));
rb_ivar_set(dr->handler, ox_at_column_id, INT2FIX(col));
}
rb_funcall2(dr->handler, ox_text_id, 1, args);
}
Expand Down
4 changes: 2 additions & 2 deletions lib/ox/sax.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ module Ox
# def end_element(name); end
#
# Initializing @line in the initializer will cause that variable to be updated before each callback with the XML line
# number. The same is true for the @column but it will be updated with the column in the XML file that is the end of
# the element or node just read. Not this is the end not the start of the node, attribute, or text.
# number. The same is true for the @column but it will be updated with the column in the XML file that is the start of
# the element or node just read.
class Sax
# Create a new instance of the Sax handler class.
def initialize()
Expand Down
2 changes: 1 addition & 1 deletion lib/ox/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

module Ox
# Current version of the module.
VERSION = '1.9.0'
VERSION = '1.9.1'
end
115 changes: 61 additions & 54 deletions test/sax_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -289,21 +289,28 @@ def test_sax_nested1

def test_sax_line_col
parse_compare(%{<?xml version="1.0"?>
<!DOCTYPE top PUBLIC "top.dtd">
<top attr="one">
<!-- family -->
<child>
<grandchild/>
</child>
<![CDATA[see data.]]>
</child>Some text.
</top>},
[[:instruct, 'xml', 1, 1],
[:attr, :version, "1.0", 1, 6],
[:end_instruct, 'xml', 1, 20],
[:start_element, :top, 2, 1],
[:attr, :attr, "one", 2, 6],
[:start_element, :child, 3, 3],
[:start_element, :grandchild, 4, 5],
[:end_element, :grandchild, 4, 17],
[:end_element, :child, 5, 3],
[:end_element, :top, 6, 1],
[:doctype, " top PUBLIC \"top.dtd\"", 2, 1],
[:start_element, :top, 3, 1],
[:attr, :attr, "one", 3, 6],
[:comment, " family ", 4, 3],
[:start_element, :child, 5, 3],
[:start_element, :grandchild, 6, 5],
[:end_element, :grandchild, 6, 17],
[:cdata, "see data.", 7, 5],
[:end_element, :child, 8, 3],
[:text, "Some text.\n", 8, 11],
[:end_element, :top, 9, 1],
], LineColSax)
end

Expand All @@ -321,7 +328,7 @@ def test_sax_element_name_mismatch
[:start_element, :child],
[:start_element, :grandchild],
[:end_element, :grandchild],
[:error, "invalid format, element start and end names do not match", 5, 10]
[:error, "invalid format, element start and end names do not match", 5, 12]
])
end

Expand Down Expand Up @@ -518,51 +525,51 @@ def test_sax_mixed
</row>
</table>
},
[[:instruct, "xml", 1, 1],
[:attr, :version, "1.0", 1, 6],
[:end_instruct, 'xml', 1, 20],
[:instruct, "ox", 2, 6],
[:attr, :version, "1.0", 2, 77],
[:attr, :mode, "object", 2, 92],
[:attr, :circular, "no", 2, 107],
[:attr, :xsd_date, "no", 2, 122],
[:end_instruct, 'ox', 2, 124],
[:doctype, " table PUBLIC \"-//ox//DTD TABLE 1.0//EN\" \"http://www.ohler.com/DTDs/TestTable-1.0.dtd\"", 3, 97],
[:start_element, :table, 4, 9],
[:start_element, :row, 5, 9],
[:attr, :id, "00004", 5, 20],
[:start_element, :cell, 6, 12],
[:attr, :id, "A", 6, 19],
[:attr, :type, "Fixnum", 6, 34],
[:text, "1234", 6, 40],
[:end_element, :cell, 6, 46],
[:start_element, :cell, 7, 12],
[:attr, :id, "B", 7, 19],
[:attr, :type, "String", 7, 34],
[:text, "A string.", 7, 45],
[:end_element, :cell, 7, 51],
[:start_element, :cell, 8, 12],
[:attr, :id, "C", 8, 19],
[:attr, :type, "String", 8, 34],
[:text, "This is a longer string that stretches over a larger number of characters.", 8, 110],
[:end_element, :cell, 8, 116],
[:start_element, :cell, 9, 12],
[:attr, :id, "D", 9, 19],
[:attr, :type, "Float", 9, 33],
[:text, "-12.345", 9, 42],
[:end_element, :cell, 9, 48],
[:start_element, :cell, 10, 12],
[:attr, :id, "E", 10, 19],
[:attr, :type, "Date", 10, 32],
[:text, "2011-09-18 23:07:26 +0900", 10, 59],
[:end_element, :cell, 10, 65],
[:start_element, :cell, 11, 12],
[:attr, :id, "F", 11, 19],
[:attr, :type, "Image", 11, 33],
[:cdata, "xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00", 11, 123],
[:end_element, :cell, 11, 130],
[:end_element, :row, 12, 9],
[:end_element, :table, 13, 9]], LineColSax)
[[:instruct, "xml"],
[:attr, :version, "1.0"],
[:end_instruct, 'xml'],
[:instruct, "ox"],
[:attr, :version, "1.0"],
[:attr, :mode, "object"],
[:attr, :circular, "no"],
[:attr, :xsd_date, "no"],
[:end_instruct, 'ox'],
[:doctype, " table PUBLIC \"-//ox//DTD TABLE 1.0//EN\" \"http://www.ohler.com/DTDs/TestTable-1.0.dtd\""],
[:start_element, :table],
[:start_element, :row],
[:attr, :id, "00004"],
[:start_element, :cell],
[:attr, :id, "A"],
[:attr, :type, "Fixnum"],
[:text, "1234"],
[:end_element, :cell],
[:start_element, :cell],
[:attr, :id, "B"],
[:attr, :type, "String"],
[:text, "A string."],
[:end_element, :cell],
[:start_element, :cell],
[:attr, :id, "C"],
[:attr, :type, "String"],
[:text, "This is a longer string that stretches over a larger number of characters."],
[:end_element, :cell],
[:start_element, :cell],
[:attr, :id, "D"],
[:attr, :type, "Float"],
[:text, "-12.345"],
[:end_element, :cell],
[:start_element, :cell],
[:attr, :id, "E"],
[:attr, :type, "Date"],
[:text, "2011-09-18 23:07:26 +0900"],
[:end_element, :cell],
[:start_element, :cell],
[:attr, :id, "F"],
[:attr, :type, "Image"],
[:cdata, "xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00xx00"],
[:end_element, :cell],
[:end_element, :row],
[:end_element, :table]])
end

def test_sax_encoding
Expand Down

0 comments on commit b39570b

Please sign in to comment.