Altova XMLSpy 2024 Enterprise Edition

After you generate code from the example schema, a test C# application is created, along with several supporting Altova libraries.

 

About the generated C# libraries

The central class of the generated code is the Doc2 class, which represents the XML document. Such a class is generated for every schema and its name depends on the schema file name. Note that this class is called Doc2 to avoid a possible conflict with the namespace name. As shown in the diagram, this class provides methods for loading documents from files, binary streams, or strings (or saving documents to files, streams, strings). For a description of this class, see the class reference ( [YourSchema].[Doc] ).

cg_cs_example_01

The Library member of the Doc2 class represents the actual root of the document.

 

According to the code generation rules mentioned in About Schema Wrapper Libraries (C#), member classes are generated for each attribute and for each element of a type. In the generated code, the name of such member classes is prefixed with MemberAttribute_ and MemberElement_, respectively. Examples of such classes are MemberAttribute_ID and MemberElement_Author, generated from the Author element and ID attribute of a book, respectively (in the diagram below, they are classes nested under BookType). Such classes enable you to manipulate programmatically the corresponding elements and attributes in the instance XML document (for example, append, remove, set value, etc). For more information, see the [YourSchemaType].MemberAttribute and [YourSchemaType].MemberElement class reference.

 

Since the DictionaryType is a complex type derived from BookType in the schema, this relationship is also reflected in the generated classes. As illustrated in the diagram below, the class DictionaryType inherits the BookType class.

cg_cs_example_02

If your XML schema defines simple types as enumerations, the enumerated values become available as Enum values in the generated code. In the schema used in this example, a book format can be hardcover, paperback, e-book, and so on. Therefore, in the generated code, these values would be available through an Enum that is a member of the BookFormatType class.

 

Writing an XML document

1.Open the LibraryTest.sln solution in Visual Studio generated from the Library schema mentioned earlier in this example.

 

While prototyping an application from a frequently changing XML schema, you may need to frequently generate code to the same directory, so that the schema changes are immediately reflected in the code. Note that the generated test application and the Altova libraries are overwritten every time when you generate code into the same target directory. Therefore, do not add code to the generated test application. Instead, integrate the Altova libraries into your project (see Integrating Schema Wrapper Libraries).

 

2.In Solution Explorer, open the LibraryTest.cs file, and edit the Example() method as shown below.

 

protected static void Example()
{
  // Create a new XML document
  Doc2 doc = Doc2.CreateDocument();
  // Append the root element
  LibraryType root = doc.Library.Append();
 
  // Create the generation date using Altova DateTime class
  Altova.Types.DateTime dt = new Altova.Types.DateTime(System.DateTime.Now);
  // Append the date to the root
  root.LastUpdated.Value = dt;
 
  // Add a new book
  BookType book = root.Book.Append();
  // Set the value of the ID attribute
  book.ID.Value = 1;
  // Set the format of the book (enumeration)
  book.Format.EnumerationValue = BookFormatType.EnumValues.eHardcover;
  // Set the Title and Author elements
  book.Title.Append().Value = "The XMLSpy Handbook";
  book.Author.Append().Value = "Altova";
 
  // Append a dictionary (book of derived type) and populate its attributes and elements
  DictionaryType dictionary = new DictionaryType(root.Book.Append().Node);
  dictionary.ID.Value = 2;
  dictionary.Title.Append().Value = "English-German Dictionary";
  dictionary.Format.EnumerationValue = BookFormatType.EnumValues.eE_book;
  dictionary.Author.Append().Value = "John Doe";
  dictionary.FromLang.Append().Value = "English";
  dictionary.ToLang.Append().Value = "German";
  // Since it's a derived type, make sure to set the xsi:type attribute of the book element
  dictionary.SetXsiType();
 
  // Optionally, set the schema location (adjust the path if
  // your schema is not in the same folder as the generated instance file)
  doc.SetSchemaLocation("Library.xsd");
 
  // Save the XML document with the "pretty print" option enabled
  doc.SaveToFile("GeneratedLibrary.xml", true);
}

 

3.Press F5 to start debugging. If the code was executed successfully, a GeneratedLibrary.xml file is created in the solution output directory (typically, bin/Debug).

 

Reading an XML document

1.Open the LibraryTest.sln solution in Visual Studio.

2.Save the code below as Library.xml to the output directory of the project (by default, bin/Debug). This is the file that will be read by the program code.

 

<?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.In Solution Explorer, open the LibraryTest.cs file, and edit the Example() method as shown below.

 

protected static void Example()
{
  // Load the XML file
  Doc2 doc = Doc2.LoadFromFile("Library.xml");
  // Get the root element
  LibraryType root = doc.Library.First;
 
  // Read the library generation date
  Altova.Types.DateTime dt = root.LastUpdated.Value;
  string dt_as_string = dt.ToString(DateTimeFormat.W3_dateTime);
  Console.WriteLine("The library generation date is: " + dt_as_string);
 
  // Iteration: for each <Book>...
  foreach (BookType book in root.Book)
  {
    // Output values of ID attribute and (first and only) title element
    Console.WriteLine("ID:    " + book.ID.Value);
    Console.WriteLine("Title: " + book.Title.First.Value);
 
    // Read and compare an enumeration value
    if (book.Format.EnumerationValue == BookFormatType.EnumValues.ePaperback)
        Console.WriteLine("This is a paperback book.");
 
    // Iteration: for each <Author>
    foreach (xs.stringType author in book.Author)
        Console.WriteLine("Author: " + author.Value);
 
    // Determine if this book is of derived type      
    if (book.Node.Attributes.GetNamedItem("xsi:type") != null)
    {
        // Find the value of the xsi:type attribute
        string xsiTypeValue = book.Node.Attributes.GetNamedItem("xsi:type").Value;
        // Get the namespace URI and the lookup prefix of this namespace
        string namespaceUri = book.Node.NamespaceURI;
        string prefix = book.Node.GetPrefixOfNamespace(namespaceUri);
 
        // if this book has DictionaryType
        if (namespaceUri == "http://www.nanonull.com/LibrarySample" && xsiTypeValue.Equals(prefix + ":DictionaryType"))
        {
          // output additional fields
          DictionaryType dictionary = new DictionaryType(book.Node);
          Console.WriteLine("Language from: " + dictionary.FromLang.First.Value);
          Console.WriteLine("Language to: " + dictionary.ToLang.First.Value);
        }
        else
        {
          throw new Exception("Unexpected book type");
        }
    }
  }
 
  Console.ReadLine();
}

 

4.Press F5 to start debugging. If the code was executed successfully, Library.xml will be read by the program code, and its contents displayed as console output.

 

Reading and writing elements and attributes

Values of attributes and elements can be accessed using the Value property of the generated member element or attribute class, for example:

 

// Output values of ID attribute and (first and only) title element
Console.WriteLine("ID:    " + book.ID.Value);
Console.WriteLine("Title: " + book.Title.First.Value);

 

To get the value of the Title element in this particular example, we also used the First() method, since this is the first (and only) Title element of a book. For cases when you need to pick a specific element from a list by index, use the At() method.

 

The class generated for each member element of a type implements the standard System.Collections.IEnumerable interface. This makes it possible to loop through multiple elements of the same type. In this particular example, you can loop through all books of a Library object as follows:

 

// Iteration: for each <Book>...
foreach (BookType book in root.Book)
{
  // your code here...              
}

 

To add a new element, use the Append() method. For example, the following code appends the root element to the document:

 

// Append the root element to the library
LibraryType root = doc.Library.Append();

 

You can set the value of an attribute (like ID in this example) as follows:

 

// Set the value of the ID attribute
book.ID.Value = 1;

 

Reading and writing enumeration values

If your XML schema defines simple types as enumerations, the enumerated values become available as Enum values in the generated code. In the schema used in this example, a book format can be hardcover, paperback, e-book, and so on. Therefore, in the generated code, these values would be available through an Enum:

ex_class_BookFormatType

To assign enumeration values to an object, use code such as the one below:

 

// Set the format of the book (enumeration)
book.Format.EnumerationValue = BookFormatType.EnumValues.eHardcover;

 

You can read such enumeration values from XML instance documents as follows:

 

// Read and compare an enumeration value
if (book.Format.EnumerationValue == BookFormatType.EnumValues.ePaperback)
Console.WriteLine("This is a paperback book.");

 

When an "if" condition is not enough, create a switch to determine each enumeration value and process it as required.

 

Working with xs:dateTime and xs:duration types

If the schema from which you generated code uses time and duration types such as xs:dateTime, or xs:duration, these are converted to Altova native classes in generated code. Therefore, to write a date or duration value to the XML document, do the following:

 

1.Construct an Altova.Types.DateTime or Altova.Types.Duration object (either from System.DateTime, or by using parts such as hours and minutes, see Altova.Types.DateTime and Altova.Types.Duration for more information).

2.Set the object as value of the required element or attribute, for example:

 

// Create the library generation date using Altova DateTime class
Altova.Types.DateTime dt = new Altova.Types.DateTime(System.DateTime.Now);
// Append the date to the root
root.LastUpdated.Value = dt;

 

To read a date or duration from an XML document, do the following:

 

1.Declare the element value (or attribute) as Altova.Types.DateTime or Altova.Types.Duration object.

2.Format the required element or attribute, for example:

 

// Read the library generation date
Altova.Types.DateTime dt = root.LastUpdated.Value;
string dt_as_string = dt.ToString(DateTimeFormat.W3_dateTime);
Console.WriteLine("The library generation date is: " + dt_as_string);

 

For more information, see Altova.Types.DateTime and Altova.Types.Duration class reference.

 

Working with derived types

If your XML schema defines derived types, you can preserve type derivation in XML documents that you create or load programmatically. Taking the schema used in this example, the following code listing illustrates how to create a new book of derived type DictionaryType:

 

// Append a dictionary (book of derived type) and populate its attributes and elements
DictionaryType dictionary = new DictionaryType(root.Book.Append().Node);
dictionary.ID.Value = 2;
dictionary.Title.Append().Value = "English-German Dictionary";
dictionary.Author.Append().Value = "John Doe";
dictionary.FromLanguage.Append().Value = "English";
dictionary.ToLanguage.Append().Value = "German";
 
// Since it's a derived type, make sure to set the xsi:type attribute of the book element
dictionary.SetXsiType();

 

Note that it is important to set the xsi:type attribute of the newly created book. This ensures that the book type will be interpreted correctly by the schema when the XML document is validated.

 

When you load data from an XML document, the following code listing shows how to identify a book of derived type DictionaryType in the loaded XML instance. First, the code finds the value of the xsi:type attribute of the book node. If the namespace URI of this node is http://www.nanonull.com/LibrarySample, and if the URI lookup prefix and type matches the value of the xsi:type attribute, then this is a dictionary:

 

    // Determine if this book is of derived type              
    if (book.Node.Attributes.GetNamedItem("xsi:type") != null)
    {
        // Find the value of the xsi:type attribute
        string xsiTypeValue = book.Node.Attributes.GetNamedItem("xsi:type").Value;
        // Get the namespace URI and the lookup prefix of this namespace
        string namespaceUri = book.Node.NamespaceURI;
        string prefix = book.Node.GetPrefixOfNamespace(namespaceUri);
 
        // if this book has DictionaryType
        if (namespaceUri == "http://www.nanonull.com/LibrarySample" && xsiTypeValue.Equals(prefix + ":DictionaryType"))
        {
            // output additional fields
            DictionaryType dictionary = new DictionaryType(book.Node);
            Console.WriteLine("Language from: " + dictionary.FromLang.First.Value);
            Console.WriteLine("Language to: " + dictionary.ToLang.First.Value);
        }
        else
        {
            throw new Exception("Unexpected book type");
        }
    }

© 2017-2023 Altova GmbH