static void svg_node_end(void *sax_cbck, const char *name, const char *name_space)
{
#ifndef SKIP_ALL
#ifdef SKIP_UNKNOWN_NODES
	u32 ns;
#endif
	GF_SVG_Parser *parser = (GF_SVG_Parser *)sax_cbck;
	SVG_NodeStack *top = (SVG_NodeStack *)gf_list_last(parser->node_stack);

	if (!top) {
		if (parser->laser_au && !strcmp(name, "sceneUnit")) {
			parser->laser_au = NULL;
			return;
		}
		if (parser->command) {
			u32 com_type = lsr_get_command_by_name(name);
			if (com_type == parser->command->tag) {
				if (parser->load->type==GF_SM_LOAD_DIMS && parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) {
					gf_sg_command_apply(parser->load->scene_graph, parser->command, 0);
					gf_sg_command_del(parser->command);
				}
				parser->command = NULL;
				return;
			}
		}
		/*error*/
		return;
	}

#ifdef SKIP_UNKNOWN_NODES
	ns = parser->current_ns;
	if (name_space)
		ns = gf_sg_get_namespace_code(parser->load->scene_graph, (char *) name_space);

	/*only remove created nodes ... */
	if (gf_xml_get_element_tag(name, ns) != TAG_UndefinedNode)
#endif
	{
		const char *the_name;
		Bool mismatch = GF_FALSE;
		SVG_Element *node = top->node;
		/*check node name...*/
		the_name = gf_node_get_class_name((GF_Node *)node);
		if (name_space && strstr(the_name, name_space) && strstr(the_name, name) ) {}
		else if (!strcmp(the_name, name) ) {}
		else mismatch = GF_TRUE;

		if (mismatch) {
			if (top->unknown_depth) {
				top->unknown_depth--;
				return;
			} else {
				svg_report(parser, GF_BAD_PARAM, "SVG depth mismatch: expecting </%s> got </%s>", the_name, name);
				return;
			}
		}
		parser->current_ns = top->current_ns;
		if (top->has_ns) gf_xml_pop_namespaces(top->node);
		gf_free(top);
		gf_list_rem_last(parser->node_stack);

		if (parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) {
			switch (node->sgprivate->tag) {
			case TAG_SVG_animateMotion:
				/*
				try to init animateMotion once all children have been parsed
				to make sure we get the mpath child if any, however, we are still not sure
				if the target is known. We can force initialisation
				because mpath children (if any have been parsed)
				*/
			{
				u32 i, count;
				SVG_DeferredAnimation *anim = NULL;
				count = gf_list_count(parser->deferred_animations);
				for (i = 0; i < count; i++) {
					anim = gf_list_get(parser->deferred_animations, i);
					if (anim->animation_elt == node) break;
					else anim = NULL;
				}
				if (anim) {
					if (svg_parse_animation(parser, gf_node_get_graph((GF_Node *)node), anim, NULL, 1)) {
						svg_delete_deferred_anim(anim, parser->deferred_animations);
					}
				}
			}
			break;
			case TAG_SVG_script:
			case TAG_SVG_handler:
				/*init script once text script is loaded*/
				gf_node_init((GF_Node *)node);
				break;
			}
			/*if we have associated event listeners, trigger the onLoad, only in playback mode */
			if (node->sgprivate->interact && node->sgprivate->interact->dom_evt) {
				GF_DOM_Event evt;
				memset(&evt, 0, sizeof(GF_DOM_Event));
				evt.type = GF_EVENT_LOAD;
				gf_dom_event_fire((GF_Node*)node, &evt);
			}

		}
	}
#ifdef SKIP_UNKNOWN_NODES
	else {
		if (top->unknown_depth) {
			top->unknown_depth--;
			if (!top->unknown_depth) {
				/*this is not 100% correct, we should track which unsupported node changed the namespace*/
				parser->current_ns = top->current_ns;
				if (parser->command_depth) parser->command_depth --;
			}
		} else if (parser->command_depth) {
			parser->command_depth--;
		} else {
			svg_report(parser, GF_BAD_PARAM, "SVG depth mismatch");
		}
	}
#endif

#endif //SKIP_ALL
}