static void svg_node_start(void *sax_cbck, const char *name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes)
{
#ifndef SKIP_ALL
	GF_SVG_Parser *parser = (GF_SVG_Parser *)sax_cbck;
	SVG_NodeStack *stack, *parent;
	SVG_Element *elt;
	SVG_Element *cond = NULL;
	u32 xmlns;
	Bool has_ns;

	parent = (SVG_NodeStack *)gf_list_last(parser->node_stack);

	/*switch to conditional*/
	if (parent && parent->node->sgprivate->tag==TAG_LSR_conditional) {
		cond = parent->node;
		parent = NULL;
	}

	/* If the loader was created with the DIMS type and this is the root element, restore the stream and AU
	context - in DIMS? we only have one stream an dcommands are stacked in the last AU of the stream*/
	if (!parent && (parser->load->type == GF_SM_LOAD_DIMS) && parser->load->ctx) {

		/*if not created, do it now*/
		if (!gf_list_count(parser->load->ctx->streams)) {
			parser->laser_es = gf_sm_stream_new(parser->load->ctx, 1, GF_STREAM_SCENE, GF_CODECID_DIMS);
			if (!parser->laser_es) {
				svg_report(parser, GF_OUT_OF_MEM, NULL);
				return;
			}
			parser->laser_es->timeScale = 1000;
			/* Create a default AU to behave as other streams (LASeR, BIFS)
			   but it is left empty, there is no notion of REPLACE Scene or NEw Scene,
			   the RAP is the graph */
			parser->laser_au = gf_sm_stream_au_new(parser->laser_es, 0, 0, GF_TRUE);
			if (!parser->laser_au) {
				svg_report(parser, GF_OUT_OF_MEM, NULL);
				return;
			}
		} else {
			parser->laser_es = gf_list_get(parser->load->ctx->streams, 0);
			parser->laser_au = gf_list_last(parser->laser_es->AUs);
		}
	}

	/*saf setup*/
	if ((!parent && (parser->load->type!=GF_SM_LOAD_SVG)) || cond) {
		u32 com_type;

		has_ns=GF_FALSE;
		svg_check_namespace(parser, attributes, nb_attributes, &has_ns);

		/*nothing to do, the context is already created*/
		if (!strcmp(name, "SAFSession")) return;
		/*nothing to do, wait for the laser (or other) header before creating stream)*/
		if (!strcmp(name, "sceneHeader")) return;
		/*nothing to do, wait for the laser (or other) header before creating stream)*/
		if (!strcmp(name, "LASeRHeader")) {
			GF_ESD *esd;

			if (!parser->load->ctx) {
				svg_report(parser, GF_BAD_PARAM, "Invalid parser context");
				return;
			}
			esd = lsr_parse_header(parser, name, name_space, attributes, nb_attributes);
			if (!esd) {
				svg_report(parser, GF_BAD_PARAM, "Invalid LASER Header");
				return;
			}
			/*TODO find a better way of assigning an ID to the laser stream...*/
			esd->ESID = 1;
			parser->laser_es = gf_sm_stream_new(parser->load->ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication);
			if (!parser->laser_es) {
				svg_report(parser, GF_OUT_OF_MEM, NULL);
				return;
			}
			if (!parser->load->ctx->root_od) {
				parser->load->ctx->root_od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG);
				if (!parser->load->ctx->root_od) {
					svg_report(parser, GF_OUT_OF_MEM, NULL);
					return;
				}
			}
			gf_list_add(parser->load->ctx->root_od->ESDescriptors, esd);
			parser->laser_es->timeScale = esd->slConfig->timestampResolution;
			return;
		}
		if (!strcmp(name, "sceneUnit") ) {
			u32 time, i;
			Bool rap;
			time = 0;
			rap =  GF_FALSE;
			if (!parser->laser_es) {
				svg_report(parser, GF_BAD_PARAM, "No LASER stream specified");
				return;
			}
			if (!gf_list_count(parser->laser_es->AUs)) rap = GF_TRUE;
			for (i=0; i<nb_attributes; i++) {
				GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
				if (!strcmp(att->name, "time")) time = atoi(att->value);
				else if (!strcmp(att->name, "rap")) rap = !strcmp(att->value, "yes") ? GF_TRUE : GF_FALSE;
			}
			/*create new laser unit*/
			parser->laser_au = gf_sm_stream_au_new(parser->laser_es, time, 0, rap);
			if (!parser->laser_au) {
				svg_report(parser, GF_OUT_OF_MEM, NULL);
				return;
			}
			return;
		}

		if (!strcmp(name, "StreamHeader") || !strcmp(name, "RemoteStreamHeader")
		        /*SAF & SAFML are just a pain ...*/
		        || !strcmp(name, "mediaHeader") || !strcmp(name, "imageHeader")
		   ) {
			char *url = NULL;
			char *src = NULL;
			const char *ID = NULL;
			u32 time, codecid, ST, i, ts_res;
			GF_ODUpdate *odU;
			GF_ObjectDescriptor *od;
			SVG_SAFExternalStream*st;
			/*create a SAF stream*/
			if (!parser->saf_es && parser->load->ctx) {
				GF_ESD *esd = (GF_ESD*)gf_odf_desc_esd_new(2);
				esd->ESID = 0xFFFE;
				esd->decoderConfig->streamType = GF_STREAM_OD;
				esd->decoderConfig->objectTypeIndication = 1;
				parser->saf_es = gf_sm_stream_new(parser->load->ctx, esd->ESID, GF_STREAM_OD, GF_CODECID_OD_V1);
				if (!parser->saf_es) {
					svg_report(parser, GF_OUT_OF_MEM, NULL);
					return;
				}
				if (!parser->load->ctx->root_od) {
					parser->load->ctx->root_od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG);
					if (!parser->load->ctx->root_od) {
						svg_report(parser, GF_OUT_OF_MEM, NULL);
						return;
					}
				}
				parser->saf_es->timeScale = 1000;
				gf_list_add(parser->load->ctx->root_od->ESDescriptors, esd);
			}
			time = 0;
			ts_res = 1000;
			codecid = ST = 0;
			for (i=0; i<nb_attributes; i++) {
				GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
				if (!strcmp(att->name, "time")) time = atoi(att->value);
				else if (!strcmp(att->name, "rap")) ;//rap = !strcmp(att->value, "yes") ? 1 : 0;
				else if (!strcmp(att->name, "url")) url = gf_strdup(att->value);
				else if (!strcmp(att->name, "streamID")) ID = att->value;
				else if (!strcmp(att->name, "objectTypeIndication")) codecid = atoi(att->value);
				else if (!strcmp(att->name, "codecID")) {
					codecid = GF_4CC(att->value[0],att->value[1],att->value[2],att->value[3]);
				}
				else if (!strcmp(att->name, "streamType")) ST = atoi(att->value);
				else if (!strcmp(att->name, "timeStampResolution")) ts_res = atoi(att->value);
				else if (!strcmp(att->name, "source")) src = att->value;

			}
			if (!strcmp(name, "imageHeader")) ST = 4;

			/*create new SAF stream*/
			st = svg_saf_get_next_available_stream(parser);
			st->stream_name = ID ? gf_strdup(ID) : NULL;

			/*create new SAF unit*/
			parser->saf_au = gf_sm_stream_au_new(parser->saf_es, time, 0, GF_FALSE);
			if (!parser->saf_au) {
				svg_report(parser, GF_OUT_OF_MEM, NULL);
				return;
			}

			odU = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
			if (!odU) {
				svg_report(parser, GF_OUT_OF_MEM, NULL);
				return;
			}
			gf_list_add(parser->saf_au->commands, odU);
			od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
			if (!od) {
				svg_report(parser, GF_OUT_OF_MEM, NULL);
				return;
			}
			gf_list_add(odU->objectDescriptors, od);
			od->objectDescriptorID = st->id;

			if (url) {
				od->URLString = url;
			} else {
				GF_MuxInfo *mux;
				GF_ESD *esd = (GF_ESD*)gf_odf_desc_esd_new(2);
				if (!esd) {
					svg_report(parser, GF_OUT_OF_MEM, NULL);
					return;
				}
				gf_list_add(od->ESDescriptors, esd);
				esd->decoderConfig->objectTypeIndication = codecid;
				esd->decoderConfig->streamType = ST;
				esd->ESID = st->id;

				mux = (GF_MuxInfo *)gf_odf_desc_new(GF_ODF_MUXINFO_TAG);
				if (!mux) {
					svg_report(parser, GF_OUT_OF_MEM, NULL);
					return;
				}
				gf_list_add(esd->extensionDescriptors, mux);

				/*global source for stream, don't use nhml dumping*/
				if (src) {
					mux->file_name = gf_strdup(src);
					st->nhml_info = NULL;
				} else {
					FILE *nhml;
					char szName[1024];
					if (parser->load->localPath) {
						strcpy(szName, parser->load->localPath);
						strcat(szName, "/");
						strcat(szName, ID ? ID : "");
					} else {
						strcpy(szName, ID ? ID : "");
					}
					strcat(szName, "_temp.nhml");
					mux->file_name = gf_strdup(szName);
					st->nhml_info = mux->file_name;
					nhml = gf_fopen(st->nhml_info, "wt");
					if (nhml) {
						gf_fprintf(nhml, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
						gf_fprintf(nhml, "<NHNTStream version=\"1.0\" timeScale=\"%d\" streamType=\"%d\" objectTypeIndication=\"%d\" inRootOD=\"no\" trackID=\"%d\">\n", ts_res, ST, codecid, st->id);
						gf_fclose(nhml);
					} else {
						GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[LASeR Parser] Error opening nhml file %s while preparing import\n", st->nhml_info));
					}
					mux->delete_file = GF_TRUE;
				}
			}
			return;
		}
		if (!strcmp(name, "mediaUnit") || !strcmp(name, "imageUnit") ) {
			FILE *nhml;
			char *id = NULL;
			char *src = NULL;
			SVG_SAFExternalStream*st;
			u32 i, rap, time, offset, length;
			rap = time = offset = length = 0;
			for (i=0; i<nb_attributes; i++) {
				GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
				if (!strcmp(att->name, "time")) time = atoi(att->value);
				else if (!strcmp(att->name, "source")) src = att->value;
				else if (!strcmp(att->name, "ref")) id = att->value;
				else if (!strcmp(att->name, "rap")) rap = !strcmp(att->value, "yes") ? 1 : 0;
				else if (!strcmp(att->name, "startOffset")) offset = atoi(att->value);
				else if (!strcmp(att->name, "length")) length = atoi(att->value);
			}
			st = svg_saf_get_stream(parser, 0, id);
			if (!st || !st->nhml_info) {
				return;
			}
			nhml = gf_fopen(st->nhml_info, "a+t");
			gf_fprintf(nhml, "<NHNTSample ");
			if (time) gf_fprintf(nhml, "DTS=\"%d\" ", time);
			if (length) gf_fprintf(nhml, "dataLength=\"%d\" ", length);
			if (offset) gf_fprintf(nhml, "mediaOffset=\"%d\" ", offset);
			if (rap) gf_fprintf(nhml, "isRAP=\"yes\" ");
			if (src) gf_fprintf(nhml, "mediaFile=\"%s\" ", src);
			gf_fprintf(nhml, "/>\n");
			gf_fclose(nhml);
			return;
		}
		if (!strcmp(name, "endOfStream") ) {
			FILE *nhml;
			char *id = NULL;
			u32 i;
			SVG_SAFExternalStream*st;
			for (i=0; i<nb_attributes; i++) {
				GF_XMLAttribute *att = (GF_XMLAttribute *) &attributes[i];
				if (!strcmp(att->name, "ref")) id = att->value;
			}
			st = svg_saf_get_stream(parser, 0, id);
			if (!st || !st->nhml_info) {
				return;
			}
			nhml = gf_fopen(st->nhml_info, "a+t");
			gf_fprintf(nhml, "</NHNTStream>\n");
			gf_fclose(nhml);
			return;
		}

		if (!strcmp(name, "endOfSAFSession") ) {
			return;
		}

		if ((parser->load->type==GF_SM_LOAD_XSR) && !parser->laser_au && !cond) {
			if (parser->load->flags & GF_SM_LOAD_CONTEXT_READY) {
				assert(parser->laser_es);
				parser->laser_au = gf_sm_stream_au_new(parser->laser_es, 0, 0, GF_FALSE);
				if (!parser->laser_au) {
					svg_report(parser, GF_OUT_OF_MEM, NULL);
					return;
				}
			} else {
				svg_report(parser, GF_BAD_PARAM, "LASeR sceneUnit not defined for command %s", name);
				return;
			}
		}
		/*command parsing*/
		com_type = lsr_get_command_by_name(name);
		if (com_type != GF_SG_UNDEFINED) {
			SVG_NodeStack *top;
			GF_Err e;
			parser->command = gf_sg_command_new(parser->load->scene_graph, com_type);
			if (!parser->command) {
				svg_report(parser, GF_OUT_OF_MEM, NULL);
				return;
			}

			/*this is likely a conditional start - update unknown depth level*/
			top = (SVG_NodeStack*)gf_list_last(parser->node_stack);
			if (top) {
				top->unknown_depth ++;
				parser->command_depth++;
			}

			e = lsr_parse_command(parser, attributes, nb_attributes);
			if (e!= GF_OK) {
				parser->command->node = NULL;
				gf_sg_command_del(parser->command);
				parser->command = NULL;
				GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[LASeR Parser] Error parsing %s command - skipping\n", (parser->load->type==GF_SM_LOAD_XSR) ? "LASeR" : "DIMS"));
				return;
			}

			if (cond) {
				GF_DOMUpdates *up = cond->children ? (GF_DOMUpdates *)cond->children->node : NULL;
				if (!up) {
					up = gf_dom_add_updates_node((GF_Node*)cond);

					if (parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK) {
						gf_node_set_callback_function((GF_Node*)up, xsr_exec_command_list);
					}
				}
				gf_list_add(up->updates, parser->command);
			} else if (parser->laser_au) {
				gf_list_add(parser->laser_au->commands, parser->command);
			}
			switch (com_type) {
			case GF_SG_LSR_NEW_SCENE:
			case GF_SG_LSR_REFRESH_SCENE:
				if (parser->laser_au) parser->laser_au->flags |= GF_SM_AU_RAP;
				break;
			}
			parser->current_ns = GF_XMLNS_SVG;
			return;
		}
	}

	if (!parent && !parser->command && (parser->load->flags & GF_SM_LOAD_CONTEXT_STREAMING)) {
		gf_sg_reset(parser->load->scene_graph);
		parser->has_root = 0;
	}

	/*something not supported happened (bad command name, bad root, ...) */
	if ((parser->has_root==1) && !parent && !parser->command)
		return;

	xmlns = parser->current_ns;
	has_ns = GF_FALSE;

	elt = svg_parse_element(parser, name, name_space, attributes, nb_attributes, parent, &has_ns);
	if (!elt) {
		if (parent) parent->unknown_depth++;
		else if (cond) parser->command_depth++;
		return;
	}
	GF_SAFEALLOC(stack, SVG_NodeStack);
	if (!stack) {
		parser->last_error = GF_OUT_OF_MEM;
		return;
	}
	stack->node = elt;
	stack->current_ns = xmlns;
	stack->has_ns = has_ns;
	gf_list_add(parser->node_stack, stack);

	if ( (gf_node_get_tag((GF_Node *)elt) == TAG_SVG_svg) &&
	        (!parser->has_root || (parser->command && !parser->command->node) )
	   ) {

		if (!parser->has_root) svg_init_root_element(parser, elt);
		if (parser->command) parser->command->node = (GF_Node*)elt;
	} else if (!parent && parser->has_root && parser->command) {
		GF_CommandField *field = (GF_CommandField *)gf_list_get(parser->command->command_fields, 0);
		if (field) {
			/*either not assigned or textContent*/
			if (field->new_node && (field->new_node->sgprivate->tag==TAG_DOMText)) {
				gf_node_unregister(field->new_node, NULL);
				field->new_node = NULL;
			}
			if (field->new_node) {
				field->field_ptr = &field->node_list;
				gf_node_list_add_child(& field->node_list, field->new_node);
				field->new_node = NULL;
				gf_node_list_add_child( & field->node_list, (GF_Node*) elt);
			} else if (field->node_list) {
				gf_node_list_add_child(& field->node_list, (GF_Node*) elt);
			} else {
				field->new_node = (GF_Node*)elt;
				field->field_ptr = &field->new_node;
			}
		} else {
			assert(parser->command->tag==GF_SG_LSR_NEW_SCENE);
			assert(gf_node_get_tag((GF_Node *)elt) == TAG_SVG_svg);
			if(!parser->command->node)
				parser->command->node = (GF_Node *)elt;
		}
	} else if (!parser->has_root ) {
		gf_list_del_item(parser->node_stack, stack);
		gf_free(stack);
		gf_node_unregister((GF_Node *)elt, NULL);
	} else if ((parser->has_root==2) && !parser->fragment_root) {
		parser->fragment_root = (GF_Node *)elt;
	}
#endif
}