madalina
madalina

Reputation: 377

create XML files from C++ program

I have this variable, a vector of double pointers like:

vector<double*> myIntersections;

which contains a vector whose elements are all a two dimensional vector of doubles. I want to create a XML file (called for example myfile.axl - with this specific extension) in which each row of the file is given by each element of the vector (so on each row one would have to elements at least vector[i][0], vector[i][1]) and the tags of the XML file are .., etc (so user defined). The file will XML should be something like:

<point name="intersectPoints" size="4" color="rgb">
  -2.68 1.82 0.0 255 0 0
  -2.63 1.03 0.0 255 0 0
</point>

where vector[0][0]=-2.68, vector[0][1]=1.82 and so on (0.0 255 0 0 being always the same) I know how to write file in C++ (I was thinking about using the fstream library), but I do not know how to create the XML tags (other than with strings in this way they will be though strings) so I am a little bit lost.

any suggestions is more than welcomed. thank you for your time, madalina

Upvotes: 7

Views: 20955

Answers (9)

Mykola Golubyev
Mykola Golubyev

Reputation: 59834

Please. Please don't create XML on your own.

Use libraries which will generate valid and correct XML file.
Same things is related to reading XML. You aren't going to read XML with ifstream, are you? So if you have XML library to read XML files I am pretty sure that this library allows XML creation.

Here is sample code with tinyxml

int main()
{
    VertexList vl;

    vl.push_back( Vertex( Point3d( -2.68, 1.82, 0.0 ), RGB( 255, 0, 0 )));
    vl.push_back( Vertex( Point3d( -2.63, 1.03, 0.0 ), RGB( 255, 0, 0 )));

    std::ostringstream ss;
    std::for_each( vl.begin(), vl.end(), VertexPrint( ss ) );

    // write xml
    TiXmlDocument doc;
    TiXmlDeclaration decl( "1.0", "", "" );  
    doc.InsertEndChild( decl );  

    TiXmlElement point( "point" );  

    TiXmlComment comment( "My Points" );
    point.InsertEndChild( comment );  

    point.SetAttribute("name", "intersectPoints");
    point.SetAttribute("size", vl.size());
    point.SetAttribute("color", "rgb");

    TiXmlText values( ss.str() );
    point.InsertEndChild( values );  

    doc.InsertEndChild( point );  
    doc.SaveFile( "out.xml" );  
}

Where Vertex

struct Point3d
{
    Point3d( double x, double y, double z ):
        x_(x), y_(y), z_(z)
    {}
    double x_;
    double y_;
    double z_;
};
struct RGB
{
    RGB( int r, int g, int b ):
        r_(r), g_(g), b_(b)
    {}
    int r_;
    int g_;
    int b_;
};
struct Vertex
{
    Vertex( const Point3d& coord, const RGB& color ):
        coord_( coord ), color_( color )
    {}
    Point3d coord_;
    RGB color_;
};
typedef std::vector< Vertex > VertexList;

and VertexPrint is

struct VertexPrint
{
    VertexPrint( std::ostringstream& result ):
        result_( result )
    {}
    void operator() ( const Vertex& v )
    {
        result_ << v.coord_.x_ <<" "<< v.coord_.y_ <<" "<< v.coord_.z_ <<" "
                << v.color_.r_ <<" "<< v.color_.b_ <<" "<< v.color_.b_ <<";";
    }
    std::ostringstream& result_;
};

You can also consider boost XML serialization

Upvotes: 7

bobmcn
bobmcn

Reputation: 1184

I have used xerces to generate XML files, and it very expensive in terms of memory and CPU usage. I eventually got "out of memory" exceptions trying to generate files with only a few hundreds of thousands of lines of XML. If you can get away with generating it directly as some other answers have suggested, and as your question implies should be possible, I would go that route. Reading and parsing is a different story, but using xerces to generate XML is overkill.

Upvotes: 1

Nemanja Trifunovic
Nemanja Trifunovic

Reputation: 24561

If you are just writing XML, a full blown parser is an overkill. Better take a look at something like Genx

Upvotes: 1

James Eichele
James Eichele

Reputation: 119144

For something simple like this, writing the tags directly would not be very complicated:

void WriteToFile(fstream& file, vector<double *> intersections)
{
    file << "<point";
    file << " name=\"intersectPoints\"";
    file << " size=\"" << intersections.size() "\"";
    file << " color=\"rgb\""
    file << ">\n"

    vector<double *>::iterator it;
    for (it=intersections.begin(); it != intersections.end(); it++)
    {
        file << (*it)[0] << " " << (*it)[1] << " " << (*it)[2] << " ";
        file << "255 0 0\n";
    }

    file << "</point>" << endl;
}

Upvotes: 0

Zack The Human
Zack The Human

Reputation: 8481

Check out TinyXml. It's extremely lightweight. From the documentation:

TinyXML uses a Document Object Model (DOM), meaning the XML data is parsed into a C++ objects that can be browsed and manipulated, and then written to disk or another output stream. You can also construct an XML document from scratch with C++ objects and write this to disk or another output stream.

I've used TinyXml in my own projects and it is a joy to use.

Edit: In addition to TinyXML, I also use ticpp (TinyXml++) which introduces more features of C++ (exceptions, templates, iterators, etc) on top of the library.

Upvotes: 5

madalina
madalina

Reputation: 377

I am looking at TinyXml now. I have downloaded it I hope I can install it. I use MacOSX, I can see the Makefile for Linux was also successfully tested for MacOSX so I will try to install it and if successfully installed worked with it.

Upvotes: 0

Emile Vrijdags
Emile Vrijdags

Reputation: 1578

To read and write xml files you would usually use an xml parser (sax or dom based)

One I have used is a sax parser called xerces

Upvotes: 0

Annerajb
Annerajb

Reputation: 932

behold a hack...

cout << "<point name=\"intersectPoints\" size=\"4\" color=\"rgb\">"<<endl;
cout << "  "<<-2.68<<" "<<1.82<<" "<<0.0<<" "<<255<<" "<<0<<" "<<0<<"";

that's how i write xml files with little overhead just save to the file the raw xml.

Upvotes: 0

Max
Max

Reputation: 3180

Assuming you are on Windows and using Visual Studio, you could use MSXML or other 3rd party libraries.

Upvotes: 0

Related Questions