Click here to Skip to main content
15,881,172 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi Guys,
Hope u all will be f9. Well i m a new in this community and working on a project. I stucked and didn't find the solution. Kindly help me out. I am working on an XML project i have to read the data from xml and then have to generate a code(javascript) and at last use this code in HTML.I am posting my code.(parse xml.h and parse xml.cpp).
C++
parse xml.h
    #pragma once
    #include <vector>
    #include <iostream>
    #include <string>
    #include <map>
    #include <fstream>
    using namespace std;
    
    namespace prog {
    
    	class MainNode
    	{
    	public: 
    		vector<Mainnode*> *elements;
    		MainNode () { elements = NULL;}
    		virtual void writeCode(fstream &outfile) = 0; 
    		
    	};
    	   class ScxmlElement : public MainNode 
    	   {
    	   public:
    		  string version, initialstate, name;
    		  ScxmlElement () { elements = new vector<Mainnode*> ();}
    		  void writeCode(fstream &outfile){
          outfile<<"var JS"<<" "<<"= new Statechart"<<" "<<"("<<initialstate<<")"<<endl;
    			  
    			 </*for (auto it = elements->begin(); it != elements->end(); ++it) {
    				  (*it)->writeCode(outfile);
                delete *it;
        }*/ //i tried to use this but got error (debug assertion fail) and then left it>
    	for (long index=0;index<(long)elements->size();++index){
    		 outfile<<"index at element: "<<(*elements).at(index)<<endl;
    				  MainNode *node = elements->at(index);
    				  outfile<<node<<endl;
    				 node->writeCode(outfile);//i think this call has problem
    				 }
    		  }
    	    };
    		class ScxmlDatamodel : public MainNode
    		{
    		public: 
    			
    			map<string,string> data;
    			void writeCode(fstream &outfile){
    	for(map<string,string>::const_iterator it= data.begin();it!=data.end();++it)
    	 outfile<<"var"<<" "<<(*it).first<<" = "<<(*it).second<<endl;
    			}
    		};
    		class ScxmlState : public MainNode
    		{
    		public:
    			string id, module;
    			ScxmlState () { elements = new vector<Mainnode*> ();}
    			void writeCode(fstream &outfile){
    	outfile<<"\nvar"<<" "<<id<<"State = new State ("<<"\""<<id<<"\""<<")"<<endl;
    			
    	for (long index=0;index<(long)elements->size();++index){
    				  MainNode *node = elements->at(index);
    				  node->writeCode(outfile);
    				}
    				outfile<<"JS"<<".states[\""<<id<<"\"] = "<<id<<"State"<<endl;
    			}
    
    		};
    		class ScxmlTransition : public MainNode
    		{
    		public: 
    			string eventname, target;
    			string cond;
    			MainNode *parent;
    			void writeCode(fstream &outfile){
     outfile<<dynamic_cast<scxmlstate*>(parent)->id<<"State.handler[\""<<eventname<<"\"] = function (event) {";
    				if(!cond.empty())
    	outfile<<"\nif("<<cond<<") return \""<<target<<"\"\nelse return null\n}";
    				else if(!target.empty())
        		outfile<<"\nreturn \""<<target<<"\" }"<<endl;
    				else outfile<<"\nreturn null }"<<endl;
    			}
    		};
    }
    class Generator {
    public:
    	string path;
    	Generator (string filepath) { path=filepath; }
    	void write(prog::ScxmlElement module){
    		fstream file(path+"tictac_gen.js", ios::out | ios::app);
    		file<<"\ndocument.write('<script language=\"javascript\" type=\"text/javascript\"src=\"statemachine.js\"></script>')"<<endl;
    		module.writeCode(file);
    		file.close();
    	}
    };


I am getting the variable values after parsing. What i want in above code that in vector 'elements' will be stored from xml and in the virtual functions when values, of node type from vector, will be detected the virtual function (in respective class) w.r.t that node should be called but its not happening. VS just stucked and go to debugger "Unhandled exception at 0x7c919af2 in pugixml parser.exe: 0xC0000005: Access violation writing location 0xdddddded.". After struggling a lot i m unable to find the error. If anyone will point out my error i will be very thank full you. The remaining code is as follows.

C++
//parse xml.cpp
#include "parse xml.h"
#include "pugixml.hpp"
#include <cstdio>
using namespace pugi;
using namespace std;

class ScxmlParser
        {
        protected:
        xml_document doc;
        public:
            ScxmlParser () {}
            prog::ScxmlElement parse();
        };

        prog::ScxmlElement ScxmlParser::parse ()
           {
               xml_parse_result result = doc.load_file("C:\FILE.xml");
               xml_node xMainNode = doc.child("scxml");
               prog::ScxmlElement module;
               module.version=xMainNode.attribute("version").value();
               if(module.version.empty())
                throw string("Attribute version missing");
                           module.initialstate=xMainNode.attribute("initialstate").value() ;
               if(module.initialstate.empty())
                throw string("Attribute initialstate missing");

               module.name=xMainNode.attribute("datamodel").value();
               if(module.name.empty())
                throw string("Attribute datamodel missing");


         prog::ScxmlDatamodel datamodel;
         string id =xMainNode.child("datamodel").child("data").attribute("id").value();
         string expr=xMainNode.child("datamodel").child("data").attribute("expr").value();
          if(id.empty() || expr.empty())
           throw string ("Specified nodes or Attributes are missing");
         else datamodel.data.insert(make_pair(id,expr));
         module.elements->push_back(&datamodel);

         for(map<string,string>::const_iterator it=datamodel.data.begin();it!=datamodel.data.end();++it)


         xml_node states=xMainNode.child("state");
         prog::ScxmlState state;
         for(xml_node states=xMainNode.child("state");states;states=states.next_sibling("state")){
             state.id=states.attribute("id").value();
             if(state.id.empty())
                  throw string ("Attribute state id missing");
                  state.module=module.name;
                  module.elements->push_back(&state);


                 prog::ScxmlTransition transition;
                for(xml_node transitions=states.child("transition");transitions;transitions=transitions.next_sibling("transition")){
                       transition.eventname=transitions.attribute("event").value();
                       if(transition.eventname.empty())
                         throw string ("Attribute transition event missing");
                       string condition=transitions.attribute("cond").value();
                     if(!condition.empty()){
                          transition.cond=condition;
                          }
                      transition.target=transitions.attribute("target").value();
                      transition.parent=&state;
                      state.elements->push_back(&transition);


                  }
            }
        return module;
        }

void main(){
    ScxmlParser p;
    string getpath;
    prog::ScxmlElement e;
    cout<< "Enter file path"<<endl;
    cin >> getpath;

    try{ e=p.parse();} catch (string s) { cout << s << endl; }
    Generator gen(getpath);

    gen.write(e);
    getchar();

}


For better and quick understanding text has been bold, where i think the problem lies. Kindly help me out. Thanks
Posted
Updated 2-Oct-11 21:34pm
v3
Comments
Philippe Mori 2-Oct-11 20:50pm    
Have you tries using a debugger and inspect the variable at the point of failure... to see if they are properly initialized.
shahz84 2-Oct-11 23:35pm    
Thanks "Philippe Mori" for your response. i have checked with debugger but not able to catch the problem what i m expecting is that from this call"(*node).writeCode(outfile);" in "class ScxmlElement : public MainNode" the control should go to the "class ScxmlDatamodel : public MainNode" because the next address in the vector is of that class object and back to the for loop in "class ScxmlElement" and then according to the next member address in the vector. Its not happening and after 1st call in "class ScxmlElement" it moves forward and then stuck but not calling the function.

You're not failing "because of pointers", but because of the confusion you have dispersed almost everywhere.

In you code the role of the various classes is not clear. As it is not clear if derivation is used for runtime-specialization or extension.

class MainNode
{
public:
    vector<mainnode*> *elements;
    MainNode () { elements = NULL;}
    virtual void writeCode(fstream &outfile) = 0;

};

What the hell is mainnode used in vector? Why is the vector instantiated through a pointer?

You write
elements->at(index)

But also write
(*node).writeCode(outfile)

(why not node->writecode(outfile)? Try to be consistent!)

You do
dynamic_cast<scxmlstate*>(parent)->id

But if you dynamic_cast it means you want to check if the runtime type of a node is ans sxcmlstate (What the hell is it? I see a ScxmlState, but not a scxmlstate). But dynamic cast may fail to NULL, but you directly address id without any check (but if you use dynamic_cast to check the type, what is the purpose to have an id ??)

The impression I have is that you are coding bottom-up, pushing statements around and attempting to let everything go at its place automatically.

I suggest you not to continue that way (you will sooner or later with a big mess that even if it may work, you'll never know WHY it works, and the day it will stop working you will have no clue about where to start for.

So throw away this mess, and start with pencil and paper, and try to fiugure out what the role of our classes is, how they relates to each other, how those relations should translated in aggregation mechanisms (embedding of a valie, pointer to dynamically allocated object you have to destroy, pointer to something owned by somebody else ...), then start writing classes, members, and proper constructor and destructors (with the sane policy that what is allocated is also deallocated, and a proper ownership if object is defined).

Then write a test program that checks that all the relations properly works and nothing had been forgot.

After that start coding input and output functions that creates the data structure based on proper input and write proper output.
 
Share this answer
 
Comments
shahz84 3-Oct-11 3:46am    
Thanks for you response. I am sorry for the mess,actually when i copied my code and choose indent then some mess of letters have been created. Well about the main class i told that i am following xml structure so MainNode is representing the main documents and all others are inherited from that. You are also write that i m following some strange approach as the task is given to me is also very strange e.g what i have done in one task, in the next i have to amend the previous done task to achieve the new task and just go like that. About dynamic_casting its my mistake i took it wrong. i m new to programming.
Stefan_Lang 3-Oct-11 5:02am    
For code, never use editors that are meant to write plain text, and therefore contain multiple built-in auto-corrections to 'fix' typos (such as capital letters in the midst of a word). There are plenty of good actual code editors and it's well worth the effort of looking for one. Stuff like syntax highlighting and auto-indenting code blocks is standard for any of them, and that alone can be a great help.
shahz84 3-Oct-11 3:51am    
one more thing if i remove dynamic_casting the problem again is the same, i think there can't be any correction possible. well thanks a lot
Emilio Garavaglia 3-Oct-11 7:50am    
It is clean that you didn't even understood what I said.
Re-reat my post carefully: I never told you to remove it
shahz84 3-Oct-11 4:11am    
about dynamic_casting since the behavior is polymorphic i thought that at
run-time the conversion from the base class to derived class will took place. i should use static_casting?
I've only skimmed over your posting, there's just too much text, but here's a few things that caught my attention:

1. Don't define public members in an abstract base class except for virtual member functions. Constructors and member variables should always be protected or private.

2. Make a habit to declare a default constructor for each class you define, and in that constructor initialize every single member variable of that class. You did that for MainNode, but not the others.

3. Assume that every pointer may be 0, and check it before dereferencing

4. Why is ScxmlElement in namespace prog, but not the other Scxml* classes?

5. You're storing addresses to local variables instead of creating new instances of your classes. Here is one example, but I've seen at least one more:
C++
prog::ScxmlElement ScxmlParser::parse ()
{
//...
    prog::ScxmlTransition transition;
//...
    state.elements->push_back(&transition);
//...
 
Share this answer
 
Thanks very much "Stefan_Lang". Main problem was "prog namespace". what i was doing i use to instantiate the classes several time with "new" but every time i forgot to add "prog::". After your reply i realized that i have one namespace. Thanks again and also sorry for any inconvenience.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900