Leer y escribir documentos XML (C++)

www.altova.com Imprimir este apartado Página anterior Subir un nivel Página siguiente

Inicio >  Guía y referencia del usuario > Generador de código > Generar código fuente a partir de esquemas o DTD > Ejemplo: usar las bibliotecas contenedoras de esquemas >

Leer y escribir documentos XML (C++)

Tras generarse el código a partir del esquema de Library (véase Ejemplo de esquema), se crea una aplicación de prueba C++ junto con varias bibliotecas Altova secundarias.

 

Información sobre las bibliotecas C++ generadas

 

En este diagrama puede ver algunas de las clases más importantes del código generado.

 

cpp_class_diagram

 

La clase central del código generado es la clase CLibrary, que representa el documento XML. Dicha clase se genera por cada esquema y su nombre depende del nombre del archivo de esquema (en nuestro ejemplo es Library.xsd). Como puede verse en el diagrama, esta clase aporta métodos para cargar documentos desde archivos, secuencias binarias o cadenas de texto (o para guardar documentos en archivos, secuencias y cadenas). Para ver una lista de los miembros que expone esta clase consulte la referencia de la clase ([SuEsquema]::[CDoc]).

 

El campo Library2 de la clase CLibrary representa la raíz real del documento. El número que aparece al final sirve para evitar conflictos entre los nombres de clase. Library es un elemento del archivo XML, de modo que en el código C++ tiene una clase plantilla como tipo (MemberElement). La clase plantilla expone métodos y propiedades para interactuar con el elemento Library. En general, cada atributo y cada elemento de un tipo del esquema recibe un tipo en el código generado con las clases plantilla MemberAttribute y MemberElement respectivamente. Para más información consulte la referencia de las clases [SuEsquema]::AtributoMiembro y [SuEsquema]::ElementoMiembro.

 

La clase CLibraryType se genera a partir del tipo complejo del esquema con el mismo nombre (véase Bibliotecas contenedoras de esquemas (C++)).  Observe que la clase CLibraryType contiene los campos Book y LastUpdated. Según la lógica mencionada previamente, estos campos corresponden al elemento Book y al atributo LastUpdated del esquema y permiten manipular elementos y atributos del documento XML de instancia mediante programación (operaciones anexar, eliminar, etc.).

 

Como DictionaryType es un tipo complejo derivado de BookType esta relación también se refleja en las clases generadas. Como puede verse en el diagrama, la clase CDictionaryType hereda la clase CBookType.

 

Si su esquema XML define tipos simples como enumeraciones, los valores enumerados están disponibles como valores Enum en el código generado. En el esquema utilizado en este ejemplo, el formato de los libros puede ser tapa dura, bolsillo, libro electrónico y audiolibro. Por tanto, en el código generado estos valores estarán disponibles a través de un Enum que es miembro de la clase CBookFormatType.

 

Escribir un documento XML

 

1.En Visual Studio abra la solución LibraryTest.sln que se generó a partir del esquema Library mencionado anteriormente.

 

Cuando cree prototipos de aplicaciones a partir de esquemas XML que cambien con frecuencia, a veces será necesario generar código una y otra vez en el mismo directorio para que los cambios en el esquema se reflejen inmediatamente en el código. Recuerde que la aplicación de prueba que se genera y las bibliotecas de Altova se sobrescribirán cada vez que genere código en el mismo directorio de destino. Por tanto, recuerde que no debe añadir código a la aplicación de prueba que se genera, sino que debe integrar las bibliotecas de Altova en el proyecto (ver Integrar bibliotecas contenedoras de esquemas).

 

2.En el explorador de soluciones abra el archivo LibraryTest.cpp y edite el método Example() como se indica a continuación:

 

#include <ctime> // obligatorio para obtener hora actual

using namespace Library; // obligatorio para trabajar con bibliotecas de Altova

 

void Example()

{

 // Crear un documento XML nuevo vacío

 CLibrary libDoc = CLibrary::CreateDocument();

 

 // Crear el elemento raíz <Library> y agregarlo al documento

 CLibraryType lib = libDoc.Library2.append();

 

 // Obtener la hora actual y establecer el atributo "LastUpdated" usando clases de Altova

 time_t t = time(NULL);        

 struct tm * now = localtime( & t );

 altova::DateTime dt = altova::DateTime(now->tm_year + 1900, now->tm_mon + 1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec);

 lib.LastUpdated = dt;

 

 // Crear un nuevo <Book> y agregarlo a la biblioteca

 CBookType book = lib.Book.append();

 

 // Establecer el atributo "ID" del libro

 book.ID = 1;

 

 // Establecer el atributo "Format" del <Book> usando una constante de enumeración

 book.Format.SetEnumerationValue( CBookFormatType::k_Paperback );

 

 // Agregar los elementos <Title> y <Author> y establecer valores

 book.Title.append() = _T("The XML Spy Handbook");

 book.Author.append() = _T("Altova");

 

 // Anexar un diccionario (libro de tipo derivado) y rellenar sus atributos y elementos

 CDictionaryType dictionary = CDictionaryType(lib.Book.append().GetNode());

 dictionary.ID = 2;

 dictionary.Format.SetEnumerationValue( CBookFormatType::k_E_book);

 dictionary.Title.append() = _T("English-German Dictionary");

 dictionary.Author.append() = _T("John Doe");

 dictionary.FromLang.append() = _T("English");

 dictionary.ToLang.append() = _T("German");

 

 // Como diccionario es un tipo derivado, establecer el atributo xsi:type del elemento book

 dictionary.SetXsiType();

 

 // De forma opcional establecer la ubicación del esquema

 libDoc.SetSchemaLocation(_T("Library.xsd"));

 

 // Guardar el documento XML en un archivo con la codificación predeterminada(UTF-8)

 // "true" hace que el archivo tenga formato pretty-print

 libDoc.SaveToFile(_T("GeneratedLibrary.xml"), true);

 

 // Destruir el documento

 libDoc.DestroyDocument();

}

 

3.Pulse F5 para iniciar la depuración. Si el código se ejecuta correctamente, el archivo GeneratedLibrary.xml se crea en el directorio de salida de la solución.

 

Leer un documento XML

 

1.Abra la solución LibraryTest.sln en Visual Studio.
2.Guarde el código que aparece a continuación como Library1.xml en un directorio que el código de programa pueda leer (p. ej. en el mismo directorio que LibraryTest.sln).

 

<?xml version="1.0" encoding="utf-8"?>
<Library xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.nanonull.com/LibrarySample" xsi:schemaLocation="http://www.nanonull.com/LibrarySample Library.xsd" LastUpdated="2016-02-03T17:10:08.4977404">  
  <Book ID="1" Format="E-book">
    <Title>The XMLSpy Handbook</Title>
    <Author>Altova</Author>    
  </Book>
  <Book ID="2" Format="Paperback" xmlns:n1="http://www.nanonull.com/LibrarySample" xsi:type="n1:DictionaryType">
    <Title>English-German Dictionary</Title>
    <Author>John Doe</Author>
    <FromLang>English</FromLang>
    <ToLang>German</ToLang>
  </Book>
</Library>

 

3.En el explorador de soluciones abra el archivo LibraryTest.cpp y edite el método Example() como se indica a continuación.

 

using namespace Library;

void Example()

{

 // Cargar documento XML

 CLibrary libDoc = CLibrary::LoadFromFile(_T("Library1.xml"));

 

 // Obtener el primer y único elemento raíz <Library>

 CLibraryType lib = libDoc.Library2.first();

 

 // Compruebe si existe un elemento:

 if (!lib.Book.exists())

 {

         tcout << "This library is empty." << std::endl;

         return;

 }

 

 // iteración: por cada <Book>...

 for (Iterator<CBookType> itBook = lib.Book.all(); itBook; ++itBook)

 {

         // valores de salida del atributo ISBN y del primer y único elemento title

         tcout << "ID: " << itBook->ID << std::endl;

         tcout << "Title: " << tstring(itBook->Title.first()) << std::endl;

         

         // leer y compara un valor de enumeración

         if (itBook->Format.GetEnumerationValue() == CBookFormatType::k_Paperback)

                 tcout << "This is a paperback book." << std::endl;

         

         // por cada <Author>...

         for (CBookType::Author::iterator itAuthor = itBook->Author.all(); itAuthor; ++itAuthor)

                 tcout << "Author: " << tstring(itAuthor) << std::endl;

         

         // alternativa: usar recuento e índice

         for (unsigned int j = 0; j < itBook->Author.count(); ++j)

                 tcout << "Author: " << tstring(itBook->Author[j]) << std::endl;

 }

 

 // Destruir el documento

 libDoc.DestroyDocument();

}

 

4.Pulse F5 para iniciar la depuración.

© 2019 Altova GmbH