¡Esta es una revisión vieja del documento!
Para trabajar con archivos .xml desde C\C++.
Una vez descargado y descomprimido nos encontramos con una serie de ficheros .cpp y .h. Los podemos añadir a un proyecto de Visual Studio si trabajamos en Windows o llamar al comando make si estamos trabajando en linux (ya viene con su makefile to mono) y directamente se compilará. Una vez compilemos y ejecutemos lo que estaremos viendo será el programa que viene de ejemplo en xmltest.cpp. Aún así para utilizarlo en tu código únicamente tendrás que añadir #include “tinyxml.h”.
TiXmlDocument doc( "demo.xml" ); if (!doc.LoadFile()) cout << "Carga incorrecta.\n";
TiXmlDocument es un objeto que representa un documento .xml, el método LoadFile carga dicho documento sobre el objeto y devuelve un boolean indicando si la carga se ha realizado correctamente.
La clase de la que heredan todas las demás subclases es TiXmlBase, inmediatamente, después de esta vienen TiXmlAttribute y TiXmlNode.
La estructura de un objeto .xml empieza con una declaración, luego tiene un elemento principal y dentro de este otros elementos. Un elemento puede contener otros elementos, texto y\o propiedades. Cada uno de estos conceptos tiene un objeto en TinyXML asociado:
setAttribute. Puedes recoger el texto, sin tener que acceder a su elemento anidado TiXmlText, mediante el método GetText.ToText.
Para ello existe la función LinkEndChild que tienen tanto los elementos de un documento como el documento en sí, esta función añade al final el elemento pasado por parámetro:
TiXmlDocument doc; TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" ); TiXmlElement * element = new TiXmlElement( "Hello" ); TiXmlText * text = new TiXmlText( "World" ); element->LinkEndChild( text ); doc.LinkEndChild( decl ); doc.LinkEndChild( element );
Montaría:
<?xml version="1.0" ?> <Hello>World</Hello>
Asignar un atributo a un elemento es fácil utilizando la función SetAttribute(string, string|int) de este, como vemos permite asignar un valor en string o uno en integer, si quisieramos asignar un número decimal utilizaríamos SetDoubleAttribute.
Para guardar un documento, una vez lo tengamos montado únicamente deberemos de llamar al método SaveFile (string) de un objeto TiXmlDocument.
doc.SaveFile("c:\\ejemplo.xml");
Una vez recojas el primer elemento del documento obtendrás como tal un TiXmlNode, a partir de este, como ya sabes, la estructura está montada en forma de árbol. Para acceder a sus nodos hijos sólo tendrás que recoger el primero con FirstChild y recorrer los elementos mediante NextSibling hasta que este método no devuelva NULL. El método Value devolvería el nombre del tag.
int countNodes (TiXmlNode* node) { if (node == NULL) return 0; TiXmlNode* child = node->FirstChild(); int i = 1; while(child != NULL) { i += countNodes(child); child = child->NextSibling(); } return i; } int main() { TiXmlDocument doc( "ex1.xml" ); if (!doc.LoadFile()) cout << "Carga incorrecta.\n"; cout << countNodes(&doc) << "\n"; system("pause"); return 0; }
Para saber el tipo de elemento que es la clase TiXmlNode tiene un método que devuelve un integer comparable a las constantes dentro de esa mismaclase: TiXmlNode::COMMENT, TiXmlNode::DECLARATION, TiXmlNode::DOCUMENT, TiXmlNode::ELEMENT, TiXmlNode::TEXT o TiXmlNode::UNKNOW.
Sólo debemos coger el primer atributo de un elemento con FirstAttribute e ir recorriendolos utilizando el Next que te devuelve el siguiente o si no NULL.
TiXmlAttribute* pAttrib=pElement->FirstAttribute(); while (pAttrib) { pAttrib=pAttrib->Next(); }
Nada, llamas al método Name y ahí lo tienes, en un stringcito tó bonito.
Recoger un valor como string es muy sencillo, únicamente hemos de llamar al método Value y este lo devuelve sin problema alguno.
Para recoger el valor de un atributo en formato numérico tenemos que recoger su objeto TiXmlAttribute correspondiente y a este le llamaríamos a los métodos QueryIntValue(int*) o QueryDoubleValue(double*); lo que hacen estos métodos es recoger el valor e introducirlo en la variable (int o double) pasada por referencia, pero como no sabemos qué tipo es este método devolverá TIXML_SUCCESS si la asignación ha sido correcta.
TiXmlAttribute* pAttrib=pElement->FirstAttribute(); if (pAttrib->QueryIntValue(&ival)==TIXML_SUCCESS) printf( "valor %d", ival); if (pAttrib->QueryDoubleValue(&dval)==TIXML_SUCCESS) printf( "valor %1.1f", dval);
Evidentemente puedes hacerlo manualmente, pero la forma más sencilla es utilizando TinyBind.