Loading...
Searching...
No Matches
XML_Parser.cc
/************************************************************************/
/* */
/* Centre for Speech Technology Research */
/* University of Edinburgh, UK */
/* Copyright (c) 1996,1997 */
/* All Rights Reserved. */
/* */
/* Permission is hereby granted, free of charge, to use and distribute */
/* this software and its documentation without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of this work, and to */
/* permit persons to whom this work is furnished to do so, subject to */
/* the following conditions: */
/* 1. The code must retain the above copyright notice, this list of */
/* conditions and the following disclaimer. */
/* 2. Any modifications must be clearly marked as such. */
/* 3. Original authors' names are not deleted. */
/* 4. The authors' names are not used to endorse or promote products */
/* derived from this software without specific prior written */
/* permission. */
/* */
/* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
/* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
/* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
/* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
/* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
/* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
/* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
/* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
/* THIS SOFTWARE. */
/* */
/*************************************************************************/
/* */
/* Author: Richard Caley (rjc@cstr.ed.ac.uk) */
/* -------------------------------------------------------------------- */
/* Recursive descent parsing skeleton. */
/* */
/*************************************************************************/
#include "EST_error.h"
#include "XML_Parser.h"
#include "rxp.h"
XML_Parser_Class::XML_Parser_Class()
{
}
void XML_Parser_Class::register_id(EST_Regex id_pattern, EST_String directory)
{
known_ids.add_item(id_pattern, directory);
}
void XML_Parser_Class::registered_ids(EST_TList<EST_String> &list)
{
EST_Litem *p;
for(p=known_ids.head(); p != 0; p= p->next())
{
EST_String re(known_ids.key(p).tostring());
EST_String &pattern = known_ids.val(p);
list.append(re);
list.append(pattern);
}
}
XML_Parser *XML_Parser_Class::make_parser(InputSource source, Entity ent, void *data)
{
return new XML_Parser(*this, source, ent, data);
}
XML_Parser *XML_Parser_Class::make_parser(InputSource source, void *data)
{
return new XML_Parser(*this, source, NULL, data);
}
XML_Parser *XML_Parser_Class::make_parser(FILE *input,
const EST_String desc,
void *data)
{
Entity ent = NewExternalEntity(0,0,strdup8(desc),0,0);
FILE16 *input16=MakeFILE16FromFILE(input, "r");
if (input16==NULL)
EST_sys_error("Can't open 16 bit '%s'", (const char *)desc);
SetCloseUnderlying(input16, 0);
return make_parser(NewInputSource(ent, input16), ent, data);
}
XML_Parser *XML_Parser_Class::make_parser(FILE *input,
void *data)
{
return make_parser(input, "<ANONYMOUS>", data);
}
XML_Parser *XML_Parser_Class::make_parser(const EST_String filename,
void *data)
{
if ( filename == "-" )
return make_parser(stdin, data);
FILE *input = fopen(filename, "r");
if (input==NULL)
EST_sys_error("Can't open '%s'", (const char *)filename);
Entity ent = NewExternalEntity(0,0,strdup8(filename),0,0);
FILE16 *input16=MakeFILE16FromFILE(input, "r");
if (input16==NULL)
EST_sys_error("Can't open 16 bit '%s'", (const char *)filename);
SetCloseUnderlying(input16, 1);
return make_parser(NewInputSource(ent, input16), data);
}
InputSource XML_Parser_Class::try_and_open(Entity ent)
{
EST_String id = ent->publicid?ent->publicid:ent->systemid;
EST_Litem *p;
int starts[EST_Regex_max_subexpressions];
int ends[EST_Regex_max_subexpressions];
for (p = known_ids.head(); p != 0; p = p->next())
{
EST_Regex &re = known_ids.key(p);
EST_String pattern(known_ids.val(p));
if (id.matches(re, 0, starts, ends))
{
EST_String res(pattern);
res.subst(id, starts, ends);
FILE *f;
FILE16 *f16;
if((f = fopen(res, "r")))
{
if(!(f16 = MakeFILE16FromFILE(f, "r")))
return 0;
SetCloseUnderlying(f16, 1);
return NewInputSource(ent, f16);
}
}
}
return EntityOpen(ent);
}
InputSource XML_Parser_Class::open_entity(Entity ent, void *arg)
{
XML_Parser *parser = (XML_Parser *)arg;
return parser->open(ent);
}
// Default do-nothing callbacks.
void XML_Parser_Class::document_open(XML_Parser_Class &c,
XML_Parser &p,
void *data)
{ (void)c; (void)p; (void)data; }
void XML_Parser_Class::document_close(XML_Parser_Class &c,
XML_Parser &p,
void *data)
{ (void)c; (void)p; (void)data; }
void XML_Parser_Class::element_open(XML_Parser_Class &c,
XML_Parser &p,
void *data,
const char *name,
XML_Attribute_List &attributes)
{ (void)c; (void)p; (void)data; (void)name; (void)attributes; }
void XML_Parser_Class::element(XML_Parser_Class &c,
XML_Parser &p,
void *data,
const char *name,
XML_Attribute_List &attributes)
{ (void)c; (void)p; (void)data; (void)name; (void)attributes;
element_open(c, p, data, name, attributes);
element_close(c, p, data, name);
}
void XML_Parser_Class::element_close(XML_Parser_Class &c,
XML_Parser &p,
void *data,
const char *name)
{ (void)c; (void)p; (void)data; (void)name; }
void XML_Parser_Class::pcdata(XML_Parser_Class &c,
XML_Parser &p,
void *data,
const char *chars)
{ (void)c; (void)p; (void)data; (void)chars; }
void XML_Parser_Class::cdata(XML_Parser_Class &c,
XML_Parser &p,
void *data,
const char *chars)
{ (void)c; (void)p; (void)data; (void)chars; }
void XML_Parser_Class::processing(XML_Parser_Class &c,
XML_Parser &p,
void *data,
const char *instruction)
{ (void)c; (void)p; (void)data; (void)instruction; }
void XML_Parser_Class::error(XML_Parser_Class &c,
XML_Parser &p,
void *data)
{ (void)c; (void)p; (void)data; }
const char *XML_Parser_Class::get_error(XML_Parser &p)
{
return p.get_error();
}
void XML_Parser_Class::error(XML_Parser_Class &c,
XML_Parser &p,
void *data,
EST_String message)
{
if (p.current_bit != NULL)
p.current_bit->error_message = message;
error(c, p, data);
}
/*************************************************************************/
/* */
/* An actual parser. */
/* */
/*************************************************************************/
XML_Parser::XML_Parser(XML_Parser_Class &pc,
InputSource s,
Entity ent,
void *d)
{
pclass=&pc;
source=s;
initial_entity=ent;
data=d;
p = NewParser();
ParserSetEntityOpener(p, XML_Parser_Class::open_entity);
ParserSetFlag(p, ReturnDefaultedAttributes, 1);
ParserSetCallbackArg(p, (void *)this);
}
XML_Parser::~XML_Parser()
{
if (initial_entity)
FreeEntity(initial_entity);
FreeDtd(p->dtd);
FreeParser(p);
}
InputSource XML_Parser::open(Entity ent)
{
return pclass->try_and_open(ent);
}
void XML_Parser::go()
{
if (p_track_context)
p_context.clear();
if (ParserPush(p, source) == -1)
EST_error("XML Parser error in push");
pclass->document_open(*pclass, *this, data);
XBit bit;
while (1)
{
current_bit = bit = ReadXBit(p);
if (bit->type == XBIT_eof)
break;
else if (bit->type == XBIT_start || bit->type == XBIT_empty)
{
Attribute b;
XML_Attribute_List att(10);
for (b=bit->attributes; b; b=b->next)
{
att.add_item(EST_String(b->definition->name), EST_String(b->value));
}
if (bit->type == XBIT_start)
{
pclass->element_open(*pclass,
*this,
data,
bit->element_definition->name,
att
);
if (p_track_context)
{
EST_String nm(bit->element_definition->name);
p_context.push(nm);
}
}
else
pclass->element(*pclass,
*this,
data,
bit->element_definition->name,
att
);
}
else if (bit->type == XBIT_end)
{
if (p_track_context)
p_context.pop();
pclass->element_close(*pclass,
*this,
data,
bit->element_definition->name
);
}
else if (bit->type == XBIT_pcdata)
{
pclass->pcdata(*pclass,
*this,
data,
bit->pcdata_chars
);
}
else if (bit->type == XBIT_cdsect)
{
pclass->cdata(*pclass,
*this,
data,
bit->cdsect_chars
);
}
else if (bit->type == XBIT_pi)
{
pclass->processing(*pclass,
*this,
data,
bit->pi_chars
);
}
else if (bit->type == XBIT_error)
{
pclass->error(*pclass,
*this,
data);
break;
}
else
{
// ignore it
}
FreeXBit(bit);
current_bit=NULL;
}
if (current_bit!=NULL)
{
FreeXBit(bit);
current_bit=NULL;
}
pclass->document_close(*pclass, *this, data);
}
void XML_Parser::track_context(bool flag)
{
p_track_context=flag;
}
void XML_Parser::track_contents(bool flag)
{
p_track_contents=flag;
}
// Stolen from xmlparser.c, will need to be tweaked for internal rxp changes.
const char *XML_Parser::get_error()
{
int linenum, charnum;
InputSource s;
XBit bit = current_bit;
if (!bit)
return "No Parse In Progress";
p_error_message =
EST_String::cat(
bit->type == XBIT_error ? "Error" : "Warning",
": ",
bit->error_message?bit->error_message:"non XML error"
);
for(s=p->source; s; s=s->parent)
{
if(s->entity->name)
{
p_error_message += " in entity \"";
p_error_message += s->entity->name;
p_error_message += "\"";
}
else
p_error_message += " in unnamed entity";
switch(SourceLineAndChar(s, &linenum, &charnum))
{
case 1:
p_error_message += EST_String::cat(" at line ",
EST_String::Number(linenum+1),
" char ",
EST_String::Number(charnum+1),
" of ");
break;
case 0:
p_error_message += EST_String::cat(" defined at line ",
EST_String::Number(linenum+1),
" char ",
EST_String::Number(charnum+1),
" of ");
break;
case -1:
p_error_message += " defined in ";
break;
}
p_error_message += EntityDescription(s->entity);
p_error_message += "\n";
}
return (const char *)p_error_message;
}
EST_String XML_Parser::context(int n)
{
return p_context.nth(n);
}
EST_Regex
Definition EST_Regex.h:55
EST_String
Definition EST_String.h:70
EST_String::Number
static EST_String Number(int i, int base=10)
Build string from an integer.
Definition EST_String.cc:1211
EST_String::subst
int subst(EST_String source, int(&starts)[EST_Regex_max_subexpressions], int(&ends)[EST_Regex_max_subexpressions])
Substitute the result of a match into a string.
Definition EST_String.cc:467
EST_String::cat
static EST_String cat(const EST_String s1, const EST_String s2=Empty, const EST_String s3=Empty, const EST_String s4=Empty, const EST_String s5=Empty, const EST_String s6=Empty, const EST_String s7=Empty, const EST_String s8=Empty, const EST_String s9=Empty)
Definition EST_String.cc:1096
EST_THash::add_item
int add_item(const K &key, const V &value, int no_search=0)
Add an entry to the table.
Definition EST_THash.cc:167
EST_TList
Definition EST_TList.h:109
EST_TList::append
void append(const T &item)
add item onto end of list
Definition EST_TList.h:191
XML_Parser_Class::XML_Parser
friend class XML_Parser
Definition XML_Parser.h:231
XML_Parser_Class::get_error
const char * get_error(XML_Parser &p)
Get the error message for the last error.
Definition XML_Parser.cc:225
XML_Parser_Class::element
virtual void element(XML_Parser_Class &c, XML_Parser &p, void *data, const char *name, XML_Attribute_List &attributes)
Definition XML_Parser.cc:186
XML_Parser_Class::make_parser
XML_Parser * make_parser(InputSource source, void *data)
Create a parser for the RXP InputSource.
Definition XML_Parser.cc:72
XML_Parser_Class::register_id
void register_id(EST_Regex id_pattern, EST_String directory)
Definition XML_Parser.cc:48
XML_Parser_Class::error
virtual void error(XML_Parser_Class &c, XML_Parser &p, void *data)
Definition XML_Parser.cc:220
XML_Parser_Class::try_and_open
InputSource try_and_open(Entity ent)
Definition XML_Parser.cc:125
XML_Parser_Class::processing
virtual void processing(XML_Parser_Class &c, XML_Parser &p, void *data, const char *instruction)
Definition XML_Parser.cc:214
XML_Parser_Class::document_close
virtual void document_close(XML_Parser_Class &c, XML_Parser &p, void *data)
Definition XML_Parser.cc:174
XML_Parser_Class::pcdata
virtual void pcdata(XML_Parser_Class &c, XML_Parser &p, void *data, const char *chars)
Definition XML_Parser.cc:202
XML_Parser_Class::document_open
virtual void document_open(XML_Parser_Class &c, XML_Parser &p, void *data)
Definition XML_Parser.cc:169
XML_Parser_Class::element_open
virtual void element_open(XML_Parser_Class &c, XML_Parser &p, void *data, const char *name, XML_Attribute_List &attributes)
Definition XML_Parser.cc:179
XML_Parser_Class::cdata
virtual void cdata(XML_Parser_Class &c, XML_Parser &p, void *data, const char *chars)
Definition XML_Parser.cc:208
XML_Parser_Class::registered_ids
void registered_ids(EST_TList< EST_String > &list)
Definition XML_Parser.cc:53
XML_Parser_Class::element_close
virtual void element_close(XML_Parser_Class &c, XML_Parser &p, void *data, const char *name)
Definition XML_Parser.cc:196
XML_Parser_Class::XML_Parser_Class
XML_Parser_Class()
Definition XML_Parser.cc:44
XML_Parser_Class::open_entity
static InputSource open_entity(Entity ent, void *arg)
Definition XML_Parser.cc:160
XML_Parser
Definition XML_Parser.h:240
XML_Parser::p
Parser p
The RXP parser object.
Definition XML_Parser.h:273
XML_Parser::current_bit
XBit current_bit
The piece of markup being processed.
Definition XML_Parser.h:259
XML_Parser::get_error
const char * get_error()
Get the error message for the last error.
Definition XML_Parser.cc:395
XML_Parser::XML_Parser
XML_Parser(XML_Parser_Class &parent, InputSource source, Entity initial_entity, void *data)
Creator used by XML_Parser_Class::make_parser().
Definition XML_Parser.cc:246
XML_Parser::data
void * data
Arbitrary data which can be used by callbacks.
Definition XML_Parser.h:270
XML_Parser::~XML_Parser
~XML_Parser()
Destructor, may close input if required.
Definition XML_Parser.cc:261
XML_Parser::open
InputSource open(Entity ent)
Open. Asks the parser class to do the work.
Definition XML_Parser.cc:269
XML_Parser::track_contents
void track_contents(bool flag)
Definition XML_Parser.cc:388
XML_Parser::go
void go()
Run the parser.
Definition XML_Parser.cc:274
XML_Parser::context
EST_String context(int n)
Definition XML_Parser.cc:450
XML_Parser::p_context
EST_TDeque< EST_String > p_context
If context is being tracked, this is a stack of element names.
Definition XML_Parser.h:276
XML_Parser::track_context
void track_context(bool flag)
Definition XML_Parser.cc:383
XML_Parser::pclass
XML_Parser_Class * pclass
Definition XML_Parser.h:256
XML_Parser::source
InputSource source
Where we are reading from.
Definition XML_Parser.h:262
XML_Parser::initial_entity
Entity initial_entity
Definition XML_Parser.h:267