0001: /* This is a simplistic xml example how to load matrix - data from xml files.
0002:  *
0003:  * For those of you unfamiliar with the standard template library (stl), simply
0004:  * suppose that vector<float> is nothing else than an one dimensional array/buffer of type float,
0005:  * just like float array[10]; 
0006:  * 
0007:  * this (hopefully) simple and self-explaning example was written for libxml2 from 
0008:  * www.xmlsoft.org, wich is avialable across many platforms, including win32.
0009:  *
0010:  * feel free to use this code as a template for your own programs.
0011:  *
0012:  * 04.2002, www.andre-krause.net
0013: */
0014: 
0015: 
0016: // create a file named "matrix.xml" from the following comment:
0017: /*
0018: <?xml version="1.0"?> 
0019: <root>
0020:     <matrix>
0021:         <r> <c>1.2</c>  <c>3.5</c>  <c>-1.2</c> </r>
0022:         <r> <c>2.4</c>  <c>1.9</c>  <c>11.8</c> </r>
0023:         <r> <c>-4.7</c> <c>6.5</c>  <c>-0.6</c> </r>
0024:     </matrix>
0025: 
0026:     <matrix>
0027:         <r> <c>+1.2</c> <c>3.5</c>  <c>-3.2</c> <c>-3.2</c> </r>
0028:         <r> <c>21.4</c> <c>2.9</c>  <c>11.8</c> <c>-1.2</c> </r>
0029:         <r> <c>-4.7</c> <c>5.5</c>  <c>-8.6</c> <c>-6.2</c> </r>
0030:         <r> <c>-4.7</c> <c>5.5</c>  <c>-8.6</c> <c>-3.9</c> </r>
0031:     </matrix>
0032: 
0033: 
0034:     <matrix>
0035:         <r> <c>1.2</c>  <c>3.5</c>  <c>-7.2</c> </r>
0036:         <r> <c>6.4</c>  <c>1.9</c>  <c>+1.8</c> </r>
0037:         <r> <c>-4.7</c> <c>6.3</c>  <c>-0.6</c> </r>
0038:         <r> <c>1.2</c>  <c>3.5</c>  <c>-7.2</c> </r>
0039:         <r> <c>6.4</c>  <c>1.9</c>  <c>+1.8</c> </r>
0040:         <r> <c>-4.7</c> <c>6.3</c>  <c>-0.6</c> </r>
0041:     </matrix>
0042: 
0043: 
0044: </root>
0045: */
0046: 
0047: //#define LIBXML_STATIC 
0048: //#define ICONV_STATIC 
0049: #include <libxml/tree.h>
0050: #include <libxml/parser.h>
0051: 
0052: 
0053: #include <iostream>
0054: #include <vector>
0055: using namespace std;
0056: 
0057: 
0058: class matrix
0059: {
0060:     protected:
0061:         // defines a two - dimensional array of type float
0062:         vector< vector< float > > m;
0063: 
0064:         // xml loading helpers
0065:         void parse_rows(xmlDocPtr doc, xmlNodePtr cur);
0066:         void parse_cols(int a, xmlDocPtr doc, xmlNodePtr cur);
0067:     public:
0068:         int size(){ return m.size(); }
0069:         // access operator to matrix data
0070:         vector<float> & operator[](const int i){ return m[i]; }
0071:         
0072:         // prints matrix
0073:         void print();
0074: 
0075:         // loads matrix data from file stream
0076:         void load_matrix(xmlDocPtr doc, xmlNodePtr cur) { parse_rows(doc,cur); }
0077:         int save_matrix(const char * fname);
0078: };
0079: 
0080: // print matrix
0081: void matrix::print()
0082: {
0083:     for(int a=0;a<m.size();a++)
0084:     {
0085:         cout << "\n";
0086:         for(int b=0;b<m[a].size();b++)
0087:         {
0088:             cout << m[a][b] << "\t";
0089:         }
0090:     }
0091: }
0092: 
0093: void matrix::parse_rows(xmlDocPtr doc, xmlNodePtr cur)
0094: {
0095:     // skip row tag <r> and walk down the xml-tree
0096:     cur = cur->xmlChildrenNode;
0097:     
0098:     // now add columns to the actual matrix row number a
0099:     int a=0;
0100:     while (cur != NULL)
0101:     {
0102:         if (!xmlStrcmp(cur->name, (const xmlChar *)"r"))
0103:         {
0104:             // add empty row to matrix
0105:             m.push_back(vector<float>());
0106:             // fill row with columns
0107:             parse_cols(a,doc,cur);
0108:             a++;
0109:         }
0110:         cur = cur->next;
0111:     }
0112: }
0113: 
0114: 
0115: void matrix::parse_cols(int a, xmlDocPtr doc, xmlNodePtr cur)
0116: {
0117: 
0118:     // skip column tag <c> and walk down the xml-tree
0119:     cur = cur->xmlChildrenNode;
0120:     
0121:     // now add columns to the actual matrix row number a
0122:     while (cur != NULL)
0123:     {
0124:         if (!xmlStrcmp(cur->name, (const xmlChar *)"c"))
0125:             m[a].push_back
0126:             (
0127:                 atof((const char*)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1))
0128:             );
0129: 
0130:         cur = cur->next;
0131:     }
0132: }
0133: 
0134: int parse_xml(const char * filename)
0135: {
0136:     xmlDocPtr doc;
0137:     xmlNodePtr cur;
0138: 
0139:     
0140:     //
0141:     // build an XML tree from a the file;
0142:     // 
0143:     doc = xmlParseFile(filename);
0144:     if (doc == NULL) return(NULL);
0145: 
0146: 
0147:     //
0148:     // Check the document is of the right kind
0149:     //
0150:     cur = xmlDocGetRootElement(doc);
0151:     if (cur == NULL)
0152:     {
0153:         cerr << "\nempty document";
0154:         xmlFreeDoc(doc);
0155:         return(NULL);
0156:     }
0157:     if (xmlStrcmp(cur->name, (const xmlChar *) "root"))
0158:     {
0159:         cerr << "document of the wrong type, root node != root";
0160:         xmlFreeDoc(doc);
0161:         return(NULL);
0162:     }
0163: 
0164: 
0165: 
0166:     //
0167:     // Now, walk the tree.
0168:     //
0169: 
0170:     // skip root tag <root> and walk down the xml-tree
0171:     cur = cur->xmlChildrenNode;
0172:     
0173:     int a=0;
0174:     // a list of matrixes to load
0175:     vector< matrix > vm;
0176: 
0177:     while(cur != NULL)
0178:     {
0179:         if (!xmlStrcmp(cur->name, (const xmlChar *) "matrix"))
0180:         {
0181:             // we have found a matrix
0182:             vm.push_back(matrix());
0183:             vm[a].load_matrix(doc,cur);
0184:             cout << "\n\nmatrix nr. " << a << ":"; vm[a].print();
0185:             a++;
0186:         }
0187:         else
0188:         {
0189:             // do some error reporting
0190:             fprintf(stderr,"document of the wrong type, was '%s', Jobs expected", cur->name);
0191:             cerr << "xmlDocDump follows\n";
0192:             xmlDocDump ( stderr, doc );
0193:             cerr << "xmlDocDump finished\n";
0194:             xmlFreeDoc(doc);
0195:             return(NULL);
0196:         }
0197:         // walk next node
0198:         cur = cur->next;
0199:     }
0200: 
0201:     // test save
0202:     vm[0].save_matrix("matrix_save.xml");
0203:     return 1;
0204: }
0205: 
0206: 
0207: int main()
0208: {
0209:     // important: Do not genrate nodes for formatting spaces
0210:     xmlKeepBlanksDefault(0);
0211: 
0212:     if( !parse_xml("matrix.xml") )
0213:     {
0214:         cerr << "error opening file.";
0215:         return 1;
0216:     }
0217: 
0218:     // Clean up everything else before quitting.
0219:     xmlCleanupParser();
0220: 
0221:     return 0;
0222: }
0223: 
0224: // this function allows for saving the matrix
0225: int matrix::save_matrix(const char * fname)
0226: {
0227: 
0228:     xmlDocPtr doc;
0229:     xmlNodePtr root;
0230:     xmlNodePtr cur;
0231:     // create new xml document with version 1.0 
0232:     doc = xmlNewDoc((const xmlChar*)"1.0");
0233: 
0234:     // compression mit zlib - 0=uncompressed - 9=max compression
0235:     xmlSetDocCompressMode (doc,9);
0236:     //xmlSetCompressMode (9);
0237: 
0238:     // create a new root node  
0239:     root = xmlNewDocNode(doc, NULL, (const xmlChar*)"root", NULL);
0240:     
0241:     xmlDocSetRootElement(doc, root);
0242: 
0243:     cur=xmlNewChild(root,NULL,(const xmlChar*)"matrix",NULL);
0244: 
0245: 
0246:     xmlNodePtr rows;
0247:     xmlNodePtr cols;
0248: 
0249:     for(int a=0;a<m.size();a++)
0250:     {
0251:         rows=xmlNewChild(cur,NULL,(const xmlChar*)"r",NULL);
0252:         for(int b=0;b<m[a].size();b++)
0253:         {
0254:             cols=xmlNewChild(rows,NULL,(const xmlChar*)"c",(const xmlChar*)"34.3");
0255:         }
0256:     }
0257:     return xmlSaveFormatFile    (fname, doc,1); // the last param specifies the formatting. 0=nonformatted, 1=indented formatting, 2= nonindented values.
0258: 
0259: }
0260: