CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15

Thread: rapidxml

  1. #1
    Join Date
    Nov 2011
    Posts
    18

    rapidxml

    Hello,

    i am trying to load and read a xml file using radipxml. Here is the code:

    Interface.h:

    Code:
    #include "../DataIO/Input.h"
    
    class CInterface{
    
    public:
    		
    	void GetInput();
    
    protected:
    
    	// To define a pointer to other class
    	CInput *pInput;
    };
    Interface.cpp:

    Code:
    #include <cstdio>
    #include <cstring>
    #include "../DataIO/Input.h" // Where Class CInput for xml file is defined
    #include "Interface.h"
    
    //Function to obtain the input data from xml file.
    // Call the Input.cpp file and his functions
    void CInterface::GetInput(){
    
    	//To define a pointer to file
    	FILE *pFile;
    	
    	const char* filename;
    	filename = "C:/Development/Test/Input.hun";
    	pFile = fopen(filename, "rt");
    
        if (pFile == NULL){ 
            puts("Couldn't open file"); 
            exit(0); 
        } 
    
    	// Call the Input.cpp file and his functions through the pointer
    	pInput->load(pFile);
            pInput->getInfo();
    }
    Input.h:

    Code:
    class CInput {
    
    private:
    
    	xml_document<> doc;	// character type defaults to char
    	vector<char> buffer; 
    
    public:
    	
    	// Definition of the function to get the data from InputFile
    	void load(FILE *pFile);
    };
    Input.cpp:

    Code:
    #include "rapidxml_utils.hpp"
    #include "Input.h"
    
    using namespace std;
    using namespace rapidxml;
    
    /**
        Load the xml document
    	make a safe-to-modify copy of input_xml
    */
    void CInput::load(FILE *pFile){
    
    	ifstream file("Input.hun");
    	/* "Read file into vector<char>" */ 
        vector<char> buffer((istreambuf_iterator<char>(file)), istreambuf_iterator<char>()); 
    	buffer.push_back('\0'); 
    	doc.parse<0>(&buffer[0]);	// 0 means default parse flags
    
    }
    The program builds without errors. But when debugging an Exception thrown: read access violation in function load. How can I solve the access violation?
    Thanks
    Last edited by 2kaud; April 10th, 2019 at 03:41 AM. Reason: Cleaned up code tags

  2. #2
    VictorN's Avatar
    VictorN is online now Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: rapidxml

    What line of your code produces this error?
    Victor Nijegorodov

  3. #3
    Join Date
    Nov 2018
    Posts
    120

    Re: rapidxml

    I guess you need to decide who is actually responsible for opening the file.
    Code:
    filename = "C:/Development/Test/Input.hun";
    	pFile = fopen(filename, "rt");
    
    	// Call the Input.cpp file and his functions through the pointer
    	pInput->load(pFile);
    Then later
    Code:
    void CInput::load(FILE *pFile){
    
    	ifstream file("Input.hun");
    1. I'm guessing the 2nd attempt to open the file barfs, because you've already opened it.
    2. You're not even using your pFile parameter anyway.

  4. #4
    Join Date
    Nov 2011
    Posts
    18

    Re: rapidxml

    Quote Originally Posted by VictorN View Post
    What line of your code produces this error?
    The line that produces the error is
    Code:
    doc.parse<0>(&buffer[0]);

  5. #5
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: rapidxml

    I suspect that the file hasn't been read because it hasn't been opened properly, so buffer initialisation using istreambuff_iterator fails so buffer is empty and has no elements (just the extra \0 added) and hence doc.parse() fails because it's trying to access elements in the vector which aren't present.

    After the ifstream statement, check that file is actually opened. After the vector statement, check that the size of buffer isn't 0. Note that the filename in GetInput() and Load() are different (load has no paths specified).

    When you do something like open a file, read, call a function etc etc you should always check that the expected operation has been carried out properly with no errors.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  6. #6
    Join Date
    Nov 2011
    Posts
    18

    Re: rapidxml

    Quote Originally Posted by 2kaud View Post
    After the ifstream statement, check that file is actually opened. After the vector statement, check that the size of buffer isn't 0. Note that the filename in GetInput() and Load() are different (load has no paths specified).
    I have check if the file was opened and it was not opened. For that I changed my load function as:
    Code:
    void CInput::load(FILE *pFile){
    
    	ifstream file(pFile);
    	/* "Read file into vector<char>" */ 
        vector<char> buffer((istreambuf_iterator<char>(file)), istreambuf_iterator<char>()); 
    	buffer.push_back('\0'); 
    	doc.parse<0>(&buffer[0]);	// 0 means default parse flags
    }
    Now the vector is not 0. And the file is opened in the GetInput function.

    I become again in the last line the same exception as above.

  7. #7
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: rapidxml

    Generally templates take types, not values. Should doc.parse<0>(&buffer[0]); be doc.parse<string>(&buffer[0]); or some other type instead?

  8. #8
    Join Date
    Nov 2011
    Posts
    18

    Re: rapidxml

    Quote Originally Posted by salem_c View Post
    I guess you need to decide who is actually responsible for opening the file.
    I have decided to open the file in the function load. My GetInput and load function are now as follows:
    Code:
    void CInterface::GetInput(){
    
    	char *fullpath;
    	fullpath = "C:/Development/Test/Input.hun";
    
    	pInput->load(fullpath);
          pInput->getInfo();
    }
    
    void CInput::load(char *fullpath){
    
    	ifstream file(fullpath);
    	if (!file){ 
    		puts("Couldn't open file");
    		exit(0); 
    	}
    
    	/* "Read file into vector<char>" */ 
           vector<char> buffer((istreambuf_iterator<char>(file)), istreambuf_iterator<char>()); 
    	buffer.push_back('\0'); 
    	doc.parse<0>(&buffer[0]);	// 0 means default parse flags
    
    }
    Quote Originally Posted by Arjay View Post
    Generally templates take types, not values. Should doc.parse<0>(&buffer[0]); be doc.parse<string>(&buffer[0]); or some other type instead?
    I am not an expertise of rapidxml, I take the line
    Code:
    doc.parse<0>(&buffer[0]);
    from the documentation at http://rapidxml.sourceforge.net/manual.html
    I think the problem for the exception comes from
    Code:
    vector<char> buffer((istreambuf_iterator<char>(file)), istreambuf_iterator<char>());
    but until now I have not solved the problem. Any suggestion?
    Last edited by laephy; April 24th, 2019 at 04:39 AM.

  9. #9
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: rapidxml

    Code:
    vector<char> buffer((istreambuf_iterator<char>(wathunfile)), istreambuf_iterator<char>());
    That isn't the same as post #8. You should know exactly which line in your program causes the exception. Use the debugger to trace through the code and find out where the exception occurs.

    PS shouldn't istreambuf_iterator be istream_iterator?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  10. #10
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,721

    Re: rapidxml

    You can use a back_inserter to read the file in the method you are using.
    I would open in binary mode.

    Code:
    void CInput::load(char *fullpath)
    {
        ifstream file(fullpath,ios::binary);    // open binary
        if (!file) 
        {
            puts("Couldn't open file");
            exit(0);
        }
    
        /* "Read file into vector<char>" */
    
        vector<char> buffer;
        std::copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), std::back_inserter(buffer));
    
        buffer.push_back('\0');
    
        doc.parse<0>(&buffer[0]);	// 0 means default parse flags
    }
    The above code might be a little slow for a large file. Another method is to get the
    size of the file and resize the vector to that size.

    Code:
    void CInput::load(char *fullpath)
    {
        ifstream file(fullpath, ios::binary);    // open binary
        if (!file)
        {
            puts("Couldn't open file");
            exit(0);
        }
    
        file.seekg(0, std::ios_base::end);
        std::streampos fileSize = file.tellg();
        file.seekg(0, std::ios_base::beg);
    
        size_t buffer_size = size_t(fileSize) + 1;  // +1 for the '\0'
    
        vector<char> buffer;
        buffer.resize(buffer_size);  
    
        /* "Read file into vector<char>" */
    
        file.read(&buffer[0], buffer_size);
    
        buffer[buffer_size - 1] = '\0';
    
        doc.parse<0>(&buffer[0]);	// 0 means default parse flags
    }

  11. #11
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: rapidxml

    From the RapidXml documentation:

    "The following code causes RapidXml to parse a zero-terminated string named text: "

    Your buffer is not a string, but a vector<char>. You may need:

    Code:
    string buffer ((istream_iterator<char>(file)), istream_iterator<char>());
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  12. #12
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,721

    Re: rapidxml

    Just a note: By default, using istream_iterator<char> will throw out whitespaces, which might not be wanted:

    Example, if the file contains:
    Code:
    <message>Hello World</message>
    the string will end up with:
    Code:
    <message>HelloWorld</message>

  13. #13
    Join Date
    Nov 2011
    Posts
    18

    Re: rapidxml

    I have eliminate the exception in function load as follows
    Code:
    void CInput::load(char *fullpath){
    
    	ifstream file(fullpath);
    	if (!file){ 
    		puts("Couldn't open file");
    		exit(0); 
    	}
    
    	/* "Read file into vector<char>" */ 
            vector<char> buffer;
    	buffer.assign((istreambuf_iterator<char>(file)), istreambuf_iterator<char>());
    	buffer.push_back('\0'); 
    	// only use xml_copy from here on!
    	xml_document<> doc;
    	// we are choosing to parse the XML declaration
    	// parse_no_data_nodes prevents RapidXML from using the somewhat surprising
    	// behavior of having both values and data nodes, and having data nodes take
    	// precedence over values when printing
    	// >>> note that this will skip parsing of CDATA nodes <<<
    	doc.parse<parse_declaration_node | parse_no_data_nodes>(&buffer[0]);
    }
    unfortunately now the program crash when the following line is executed.

    Code:
    doc.parse<parse_declaration_node | parse_no_data_nodes>(&buffer[0]);
    In particular when the function parse is executed during parse and append new child where text before crash is /Project>. It is possible that the problem comes from my xml file? or comes from the load function?
    Last edited by laephy; April 24th, 2019 at 04:38 AM.

  14. #14
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: rapidxml

    What debugging of the rapidxml code have you done? Have you traced into the code to see what is happening and why an exception is caused? RapidXML is a set of .hpp header c++ files, so the source is available. Have you tried asking the question on the RapidXML discussion forum?
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  15. #15
    Join Date
    Nov 2011
    Posts
    18

    Re: rapidxml

    Quote Originally Posted by laephy View Post
    In particular when the function parse is executed during parse and append new child where text before crash is /Project>. It is possible that the problem comes from my xml file? or comes from the load function?
    The problem was at the xml file. I forgot to close a child. Now the code compile and load the xml without problem. Thanks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured