From a907b29b6ca6a0bf231acf58e90154756e8de132 Mon Sep 17 00:00:00 2001 From: mfranz Date: Fri, 29 Jun 2007 15:34:38 +0000 Subject: [PATCH] add parsexml() function, which is a wrapper around the built-in easyxml parser. Advantages over xml.nas: (reviewed and OK'ed by Andy) - faster (33% ... only. I had hoped for more.) - more standards compliant - should support UTF - I don't have to support it. ;-) Usage: parsexml( [, [, [, [, ]]]]); is an absolute file path, the rest are optional callback functions. Example: parsexml("/tmp/foo.xml", nil, nil, func(d) { print("DATA FOUND: ", d) }); --- src/Scripting/NasalSys.cxx | 89 +++++++++++++++++++++++++++++++++++++- src/Scripting/NasalSys.hxx | 21 +++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index bb3ab5590..ebe6dd654 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -358,6 +359,36 @@ static naRef f_directory(naContext c, naRef me, int argc, naRef* args) return result; } +// Parse XML file. +// parsexml( [, [, [, [, ]]]]); +// +// ... absolute path of an XML file +// ... callback function with two args: tag name, attribute hash +// ... callback function with one arg: tag name +// ... callback function with one arg: data string +// ... callback function with two args: target string, data string +// (pi = "processing instruction") +// All four callback functions are optional and default to nil. +// The function returns nil on error, and the file name otherwise. +static naRef f_parsexml(naContext c, naRef me, int argc, naRef* args) +{ + if(argc < 1 || !naIsString(args[0])) + naRuntimeError(c, "bad/missing argument to parsexml()"); + + const char* file = naStr_data(args[0]); + std::ifstream input(file); + NasalXMLVisitor visitor(c, argc, args); + try { + readXML(input, visitor); + } catch (const sg_exception& e) { + string msg = string("parsexml(): file '") + file + "' " + + e.getFormattedMessage(); + naRuntimeError(c, msg.c_str()); + return naNil(); + } + return args[0]; +} + // Return UNIX epoch time in seconds. static naRef f_systime(naContext c, naRef me, int argc, naRef* args) { @@ -462,6 +493,7 @@ static struct { char* name; naCFunction func; } funcs[] = { { "rand", f_rand }, { "srand", f_srand }, { "directory", f_directory }, + { "parsexml", f_parsexml }, { "systime", f_systime }, { "carttogeod", f_carttogeod }, { "geodtocart", f_geodtocart }, @@ -586,7 +618,7 @@ void FGNasalSys::loadPropertyScripts() loadModule(p, module); } */ - + const char* src = n->getStringValue("script"); if(!n->hasChild("script")) src = 0; // Hrm... if(src) @@ -914,3 +946,58 @@ FGNasalModelData::~FGNasalModelData() } + +// NasalXMLVisitor class: handles EasyXML visitor callback for parsexml() +// +NasalXMLVisitor::NasalXMLVisitor(naContext c, int argc, naRef* args) : + _c(naSubContext(c)), + _start_element(argc > 1 && naIsFunc(args[1]) ? args[1] : naNil()), + _end_element(argc > 2 && naIsFunc(args[2]) ? args[2] : naNil()), + _data(argc > 3 && naIsFunc(args[3]) ? args[3] : naNil()), + _pi(argc > 4 && naIsFunc(args[4]) ? args[4] : naNil()) +{ +} + +void NasalXMLVisitor::startElement(const char* tag, const XMLAttributes& a) +{ + if(naIsNil(_start_element)) return; + naRef attr = naNewHash(_c); + for(int i=0; i(s), + n < 0 ? strlen(s) : n); +} + + diff --git a/src/Scripting/NasalSys.hxx b/src/Scripting/NasalSys.hxx index 1a02caaf4..a772ebcd2 100644 --- a/src/Scripting/NasalSys.hxx +++ b/src/Scripting/NasalSys.hxx @@ -5,6 +5,7 @@ #include #include #include +#include #include SG_USING_STD(map); @@ -160,4 +161,24 @@ private: SGConstPropertyNode_ptr _unload; }; + +class NasalXMLVisitor : public XMLVisitor { +public: + NasalXMLVisitor(naContext c, int argc, naRef* args); + virtual ~NasalXMLVisitor() { naFreeContext(_c); } + + virtual void startElement(const char* tag, const XMLAttributes& a); + virtual void endElement(const char* tag); + virtual void data(const char* str, int len); + virtual void pi(const char* target, const char* data); + +private: + void call(naRef func, int num = 0, naRef a = naNil(), naRef b = naNil()); + naRef make_string(const char* s, int n = -1); + + naContext _c; + naRef _arg[2]; + naRef _start_element, _end_element, _data, _pi; +}; + #endif // __NASALSYS_HXX -- 2.39.5