+
+// NasalXMLVisitor class: handles EasyXML visitor callback for parsexml()
+//
+NasalXMLVisitor::NasalXMLVisitor(naContext c, int argc, naRef* args) :
+ _c(naSubContext(c)),
+ _start_element(argc > 1 ? args[1] : naNil()),
+ _end_element(argc > 2 ? args[2] : naNil()),
+ _data(argc > 3 ? args[3] : naNil()),
+ _pi(argc > 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<a.size(); i++) {
+ naRef name = make_string(a.getName(i));
+ naRef value = make_string(a.getValue(i));
+ naHash_set(attr, name, value);
+ }
+ call(_start_element, 2, make_string(tag), attr);
+}
+
+void NasalXMLVisitor::endElement(const char* tag)
+{
+ if(!naIsNil(_end_element)) call(_end_element, 1, make_string(tag));
+}
+
+void NasalXMLVisitor::data(const char* str, int len)
+{
+ if(!naIsNil(_data)) call(_data, 1, make_string(str, len));
+}
+
+void NasalXMLVisitor::pi(const char* target, const char* data)
+{
+ if (!naIsNil(_pi)) call(_pi, 2, make_string(target), make_string(data));
+}
+
+void NasalXMLVisitor::call(naRef func, int num, naRef a, naRef b)
+{
+ naRef args[2];
+ args[0] = a;
+ args[1] = b;
+ naCall(_c, func, num, args, naNil(), naNil());
+ if(naGetError(_c))
+ naRethrowError(_c);
+}
+
+naRef NasalXMLVisitor::make_string(const char* s, int n)
+{
+ return naStr_fromdata(naNewString(_c), const_cast<char *>(s),
+ n < 0 ? strlen(s) : n);
+}
+
+