00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include "autoconfig.h"
00034 #endif
00035
00036 #ifdef HAVE_EXPAT
00037
00038 #include "parser.h"
00039
00040 using namespace zmm;
00041 using namespace mxml;
00042
00043 #include "mxml.h"
00044 #include "tools.h"
00045
00046 void XMLCALL Parser::element_start(void *userdata, const char *name, const char **attrs)
00047 {
00048 Parser *parser = (Parser *)userdata;
00049 Ref<Element> el(new Element(name));
00050 for (int i = 0; attrs[i]; i += 2)
00051 {
00052 el->addAttribute(attrs[i], attrs[i + 1]);
00053 }
00054
00055 if (parser->document->getRoot() == nil)
00056 {
00057 parser->document->setRoot(el);
00058 parser->curEl = el;
00059 }
00060 else if (parser->curEl != nil)
00061 {
00062 parser->curEl->appendElementChild(el);
00063 parser->elements->push(parser->curEl);
00064 parser->curEl = el;
00065 }
00066 else
00067 {
00068
00069 print_backtrace();
00070 }
00071 }
00072
00073 void XMLCALL Parser::element_end(void *userdata, const char *name)
00074 {
00075 Parser *parser = (Parser *)userdata;
00076 parser->curEl = parser->elements->pop();
00077 }
00078
00079 void XMLCALL Parser::character_data(void *userdata, const XML_Char *s, int len)
00080 {
00081 Parser *parser = (Parser *)userdata;
00082 String text = String(s, len);
00083
00084 if (text != nil)
00085 {
00086 Ref<Text> textEl(new Text(text));
00087 if (parser->curEl == nil)
00088 parser->document->appendChild(RefCast(textEl, Node));
00089 else
00090 parser->curEl->appendChild(RefCast(textEl, Node));
00091 }
00092 }
00093
00094 void XMLCALL Parser::comment_callback(void *userdata, const XML_Char *s)
00095 {
00096 Parser *parser = (Parser *)userdata;
00097 String text = s;
00098 if (text != nil)
00099 {
00100 Ref<Comment> cm(new Comment(text));
00101 if (parser->curEl == nil)
00102 parser->document->appendChild(RefCast(cm, Node));
00103 else
00104 parser->curEl->appendChild(RefCast(cm, Node));
00105 }
00106 }
00107
00108 void XMLCALL Parser::default_callback(void *userdata, const XML_Char *s, int len)
00109 {
00110 Parser *parser = (Parser *)userdata;
00111 String text = String(s, len);
00112
00113 if (text.charAt(0) == '<')
00114 parser->ignoreNextDefaultNewline = true;
00115 else
00116 {
00117 bool add_as_character_data = true;
00118 if (parser->ignoreNextDefaultNewline)
00119 {
00120 parser->ignoreNextDefaultNewline = false;
00121 if (text == _("\n"))
00122 add_as_character_data = false;
00123 }
00124 if (add_as_character_data)
00125 character_data(userdata, s, len);
00126 }
00127
00128 }
00129
00130 Parser::Parser()
00131 {
00132 ignoreNextDefaultNewline = false;
00133 }
00134
00135 Ref<Document> Parser::parseFile(String filename)
00136 {
00137 Ref<Context> ctx(new Context(filename));
00138 return parse(ctx, read_text_file(filename));
00139 }
00140
00141 Ref<Document> Parser::parseString(String str)
00142 {
00143 Ref<Context> ctx(new Context(_("")));
00144 return parse(ctx, str);
00145 }
00146
00147 Ref<Document> Parser::parse(Ref<Context> ctx, String input)
00148 {
00149 XML_Parser parser = XML_ParserCreate(NULL);
00150 if (!parser)
00151 throw Exception(_("Unable to allocate XML parser"));
00152
00153 XML_SetUserData(parser, this);
00154 XML_SetElementHandler(parser, Parser::element_start, Parser::element_end);
00155 XML_SetCharacterDataHandler(parser, Parser::character_data);
00156 XML_SetCommentHandler(parser, Parser::comment_callback);
00157 XML_SetDefaultHandler(parser, Parser::default_callback);
00158
00159 document = Ref<Document>(new Document());
00160 elements = Ref<ObjectStack<Element> >(new ObjectStack<Element>(8));
00161
00162 if (XML_Parse(parser, input.c_str(), input.length(), 1) != XML_STATUS_OK)
00163 {
00164 ctx->line = XML_GetCurrentLineNumber(parser);
00165 ctx->col = XML_GetCurrentColumnNumber(parser);
00166 String message = XML_ErrorString(XML_GetErrorCode(parser));
00167 XML_ParserFree(parser);
00168 throw ParseException(message, ctx);
00169 }
00170
00171 XML_ParserFree(parser);
00172 return document;
00173 }
00174
00175 #endif