Lesen und Schreiben von XML-Dokumenten (C#)

www.altova.com Dieses Kapitel drucken Vorherige Seite Eine Ebene nach oben Nächste Seite

Startseite >  Code Generator > Generieren von Code anhand von XML-Schemas oder DTDs > Beispiel: Verwendung der Schema Wrapper-Bibliotheken >

Lesen und Schreiben von XML-Dokumenten (C#)

Nachdem Sie anhand des Schemas "Library" (siehe Beispielschema) Code generiert haben, wird eine C#-Testapplikation sowie eine Reihe von unterstützenden Altova-Bibliotheken generiert.

 

Informationen zu den generierten C#-Bibliotheken

Im folgenden Diagramm sehen Sie einige der wichtigsten Klassen des generierten Codes.

csharp_class_diagram

 

Die zentrale Klasse des generierten Codes ist die Klasse Library2. Sie repräsentiert das XML-Dokument. Eine solche Klasse wird für jedes Schema generiert. Ihr Name hängt vom Namen der Schemadatei ab (in diesem Beispiel Library.xsd). Beachten Sie, dass diese Klasse den Namen Library2 erhält, um einen möglichen Konflikt mit dem Namespace-Namen zu vermeiden. Wie im Diagramm gezeigt, bietet diese Klasse Methoden zum Laden von Dokumenten aus Dateien, Binär-Streams oder Strings (oder zum Speichern von Dokumenten in Dateien, Streams, Strings). In der Referenz zur Klasse ([YourSchema].[Doc]) finden Sie eine Beschreibung dieser Klasse.

 

Der Member Library3 der Klasse Library2 stellt die eigentliche Root des Dokuments dar. Die Zahl am Ende dient dazu, einen Namenskonflikt mit dem Klassennamen zu vermeiden.

 

Gemäß den im Kapitel Informationen zu Schema Wrapper-Bibliotheken (C#) angeführten Codegenerierungsregeln werden für jedes Attribut und jedes Element eines Typs Member-Klassen generiert. Der Name solcher Member-Klassen erhält im generierten Code das Präfix MemberAttribute_ bzw. MemberElement_. Im obigen Diagramm sind Beispiele für solche Klassen MemberAttribute_ID und MemberElement_Author, die anhand des Elements Author bzw. des Attributs ID eines Buchs generiert wurden. Sie ermöglichen die programmatische Bearbeitung (z.B. Anhängen, Entfernen, Wert definieren, usw.) der entsprechenden Elemente und Attribute im XML-Instanzdokument. Nähere Informationen dazu finden Sie in der Referenz zur Klasse unter [YourSchemaType].MemberAttribute und [YourSchemaType].MemberElement.

 

Da der Typ DictionaryType ein complexType ist, der im Schema von BookType abgeleitet wurde, wird diese Beziehung auch in den generierten Klassen übernommen. Im Diagramm sehen Sie, dass die Klasse DictionaryType die Klasse BookType erbt.

 

Wenn in Ihrem XML-Schema simpleTypes als Enumerationen definiert sind, so stehen die enumerierten Werte im generierten Code als Enum-Werte zur Verfügung. In dem in diesem Beispiel verwendeten Schema gibt es die Buchformate hardcover, paperback, e-book, usw. Im generierten Code stehen diese Werte folglich in Form einer Enum, d.h. als Member der Klasse BookFormatType, zur Verfügung.

 

Schreiben eines XML-Dokuments

1.Öffnen Sie die anhand des Schemas "Library" generierte Lösung LibraryTest.sln in Visual Studio.

 

Beim Erstellen eines Prototyps einer Applikation anhand eines häufig geänderten XML-Schemas müssen Sie eventuell immer wieder Code im selben Verzeichnis generieren, damit die Änderungen am Schema sofort im Code berücksichtigt werden. Beachten Sie, dass die generierte Testapplikation und die Altova-Bibliotheken jedes Mal, wenn Sie Code im selben Zielverzeichnis generieren, überschrieben werden. Fügen Sie daher keinen Code zur generierten Testapplikation hinzu, sondern integrieren Sie stattdessen die Altova-Bibliotheken in Ihr Projekt (siehe Integrieren von Schema Wrapper-Bibliotheken).

 

2.Öffnen Sie die Datei LibraryTest.cs im Solution Explorer und bearbeiten Sie die Methode Example() wie unten gezeigt.

 

      protected static void Example()
      {
          // Create a new XML library
          Library2 doc = Library2.CreateDocument();
          // Append the root element
          LibraryType root = doc.Library3.Append();
 
          // 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;
 
          // 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);
      }

 

1.Drücken Sie F5, um den Debugger zu starten. Wenn der Code erfolgreich ausgeführt wurde, wird im Lösungsausgabeverzeichnis (normalerweise bin/Debug) die Datei GeneratedLibrary.xml erstellt.

 

Lesen eines XML-Dokuments

1.Öffnen Sie die Lösung LibraryTest.sln in Visual Studio.
2.Speichern Sie den unten gezeigten Code unter dem Namen Library.xml im Ausgabeverzeichnis (standardmäßig bin/Debug). Dies ist die Datei, die vom Programmcode gelesen wird.

 

<?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>

 

1.Öffnen Sie die Datei LibraryTest.cs im Solution Explorer und bearbeiten Sie die Methode Example() wie unten gezeigt.

 

      protected static void Example()
      {
          // Load the XML file into a new Library instance
          Library2 doc = Library2.LoadFromFile("Library.xml");
          // Get the root element
          LibraryType root = doc.Library3.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();
      }

 

2.Drücken Sie F5, um den Debugger zu starten. Wenn der Code erfolgreich ausgeführt wurde, wird Library.xml vom Programmcode gelesen und ihr Inhalt wird als Konsolenausgabe angezeigt.

 

Lesen und Schreiben von Elemente und Attributen

Die Werte von Attributen und Elementen können über die Eigenschaft Value der generierten Member-Element- bzw. Attribut-Klasse gelesen werden, z.B.:

 

// Output values of ID attribute and (first and only) title element

Console.WriteLine("ID:    " + book.ID.Value);

Console.WriteLine("Title: " + book.Title.First.Value);

 

Um in diesem konkreten Beispiel den Wert des Elements Title abzurufen, haben wir auch die Methode First() verwendet, da es sich hier um des erste (und einzige) Title-Element eines Buchs handelt. In Fällen, in denen ein bestimmtes Element nach dem Index aus einer Liste gewählt werden soll, verwenden Sie die Methode At().

 

Die für die einzelnen Member-Elemente eines Typs generierte Klasse implementiert die Standardschnittstelle System.Collections.IEnumerable. Auf diese Art können mehrere Elemente desselben Typs in einer Schleife verarbeitet werden. In diesem konkreten Beispiel können Sie alle Bücher eines Library-Objekts folgendermaßen in einer Schleife verarbeiten:

 

// Iteration: for each <Book>...

foreach (BookType book in root.Book)

{

  // your code here...                                        

}

 

Mit Hilfe der Methode Append()können Sie ein neues Element hinzufügen. Im folgenden Code wird z.B. das Root-Element an das Dokument angehängt:

 

// Append the root element to the library

LibraryType root = doc.Library3.Append();

 

Sie können den Wert eines Attributs (wie ID in diesem Beispiel) folgendermaßen definieren:

 

// Set the value of the ID attribute

book.ID.Value = 1;

 

Nähere Informationen dazu finden Sie in der Referenz zu den Klassen [YourSchemaType].MemberAttribute und [YourSchemaType].MemberElement.

 

Lesen und Schreiben von Enumerationswerten

Wenn in Ihrem XML-Schema simpleTypes als Enumerationen definiert sind, so stehen die enumerierten Werte im generierten Code als Enum-Werte zur Verfügung. In dem in diesem Beispiel verwendeten Schema gibt es die Buchformate hardcover, paperback, e-book, usw. Im generierten Code stehen diese Werte folglich in Form einer Enum zur Verfügung.

 

ex_class_BookFormatType

Mit Hilfe von Code wie dem unten gezeigten können Sie einem Objekt Enumerationswerte zuweisen.:

 

// Set the format of the book (enumeration)

book.Format.EnumerationValue = BookFormatType.EnumValues.eHardcover;

 

Solche Enumerationswerte können folgendermaßen aus XML-Instanzdokumenten ausgelesen werden:

 

// Read and compare an enumeration value

if (book.Format.EnumerationValue == BookFormatType.EnumValues.ePaperback)

Console.WriteLine("This is a paperback book.");

 

Wenn eine "if"-Bedingung nicht genügt, erstellen Sie einen Switch, um jeden Enumerationswert zu ermitteln und wie erforderlich zu verarbeiten.

 

Arbeiten mit den Typen xs:dateTime und xs:duration

Wenn im Schema, anhand dessen Sie Code generiert haben, Uhrzeit- und Zeitdauer-Typen wie xs:dateTime oder xs:duration vorkommen, so werden diese im generierten Code in native Altova-Klassen konvertiert. Gehen Sie daher folgendermaßen vor, um einen Datums- oder Zeitdauerwert in das XML-Dokument zu schreiben:

 

1.Erstellen Sie ein Altova.Types.DateTime- oder Altova.Types.Duration-Objekt (entweder anhand von System.DateTime oder durch Verwendung von Teilen wie Stunden und Minuten; nähere Informationen siehe Altova.Types.DateTime und Altova.Types.Duration ).
2.Definieren Sie das Objekt als Wert des benötigten Elements oder Attributs, z.B.:

 

// 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;

 

Um ein Datum oder eine Zeitdauer aus einem XML-Dokument zu lesen, gehen Sie folgendermaßen vor:

 

1.Deklarieren Sie den Elementwert (oder den Attributwert) als Altova.Types.DateTime- oder Altova.Types.Duration-Objekt.
2.Formatieren Sie das benötige Element oder Attribut, z.B.:

 

// 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);

 

Nähere Informationen dazu finde Sie in der Referenz zu den Klassen Altova.Types.DateTime und Altova.Types.Duration.

 

Arbeiten mit abgeleiteten Typen

Wenn in Ihrem XML-Schema abgeleitete Typen (derived types) definiert sind, so können Sie die Typableitung in programmatisch erstellten oder geladenen XML-Dokumenten beibehalten. Im folgenden Codefragment wird gezeigt, wie Sie anhand des in diesem Beispiel verwendeten Schemas ein neues Buch mit dem abgeleiteten Typ DictionaryType erstellen.

 

// 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();

 

Beachten Sie, dass es wichtig ist, dass Sie das xsi:type Attribut des neu erstellten Buchs definieren. Damit stellen Sie sicher, dass der Buchtyp korrekt vom Schema interpretiert wird, wenn das XML-Dokument validiert wird.

 

Im folgenden Codefragment gezeigt, wie ein Buch vom abgeleiteten Typ DictionaryType in der geladenen XML-Instanz identifiziert wird, wenn Sie Daten aus einem XML-Dokument laden. Zuerst wird im Code der Wert des xsi:type-Attributs des Buchs gefunden. Wenn die Namespace URI dieses Node http://www.nanonull.com/LibrarySample lautet und wenn das URI-Lookup-Präfix und der Typ mit dem Wert des xsi:type-Attributs übereinstimmen, so handelt es sich um ein Wörterbuch:

 

    // 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");
        }
    }


© 2019 Altova GmbH