Altova XMLSpy 2023 Enterprise Edition

示例Schema生成代码后,将生成一个测试C#应用程序以及多个支持的Altova库。

 

关于生成的C#库

生成的代码的中心类是Doc2类,它表示XML文档。为每个Schema生成这样的类,其名称取决于Schema文件名。请注意,将此类命名为Doc2以避免可能与命名空间名称发生冲突。如图所示,此类提供了从文件、二进制流或字符串中加载文档(或将文档保存到文件、流和字符串)的方法。有关此类的描述,请参见类引用([YourSchema].[Doc] )。

cg_cs_example_01

Doc2类的Library成员表示文档的实际根。

 

根据关于Schema包装库(C#)中的代码生成规则,将为特定类型的每个特性和元素生成成员类。在生成的代码中,此类成员类的名称将分别以MemberAttribute_MemberElement_为前缀。此类的示例是MemberAttribute_IDMemberElement_Author,它们分别从图书的Author元素和ID特性生成(在下图中,它们是嵌套在BookType下的类)。它们允许您对XML实例文档中的相应元素和特性进行编程操作(例如追加、删除、设置值等)。有关更多信息,请参见[YourSchemaType].MemberAttribute and [YourSchemaType].MemberElement类引用。

 

由于DictionaryType是一个复杂类型,从Schema中的BookType派生,因此这一关系也反映在生成的类中。如下图所示,DictionaryType类继承了BookType类。

cg_cs_example_02

如果简单类型在您的XML Schema中定义为枚举,则枚举值将在生成的代码中作为Enum值可用。在本例使用的Schema中,有精装、平装、电子书等图书格式。因此,在生成的代码中,这些值以Enum的形式提供,即作为BookFormatType类的成员。

 

编写XML文档

1.在Visual Studio中打开从“库”Schema生成的LibraryTest.sln解决方案。

 

在根据频繁更改的XML Schema对应用程序进行原型设计时,您可能需要频繁地将代码生成到同一目录,从而将Schema更改及时反映在代码中。请注意,每次将代码生成到同一个目标目录中时,都会覆盖生成的测试应用程序和Altova库。因此,不能将代码添加到生成的测试应用程序中。取而代之的是,将Altova库集成到您的项目中(参见集成Schema包装库)。

 

2.在解决方案资源管理器中打开LibraryTest.cs文件,并编辑Example()方法,如下所示。

 

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.F5开始调试。如果成功运行代码,则会在解决方案输出目录(通常是bin/Debug)中创建GeneratedLibrary.xml文件。

 

读取XML文档

1.在Visual Studio中打开LibraryTest.sln解决方案。

2.将下方代码以Library.xml形式保存到项目的输出目录(默认是bin/Debug)。这是程序代码读取的文件。

 

<?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.在解决方案资源管理器中打开LibraryTest.cs文件,并编辑Example()方法,如下所示。

 

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.F5开始调试。如果成功运行代码,程序代码会读取Library.xml并将其内容显示为控制台输出。

 

读取和编写元素和特性

使用生成的成员元素或特性类的Value属性可访问特性和元素的值。例如:

 

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

 

要在此示例中检索Title元素的值,我们还可以使用First()方法,因为这是图书的第一个(也是唯一一个)Title元素。如果要按索引从列表中选择一个特定元素,则使用At() 方法。

 

为特定类型的每个成员元素生成的类实现标准System.Collections.IEnumerable 接口。这样就可以循环处理多个相同类型的元素。在此示例中,您可以循环访问Library对象的所有图书,如下所示:

 

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

 

要添加新元素,请使用Append()方法。例如,以下代码将根元素追加到文档:

 

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

 

您可以设置特性(如本例中的ID)的值,如下所示:

 

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

 

读取和编写枚举值

如果简单类型在您的XML Schema中定义为枚举,则枚举值将在生成的代码中作为Enum值可用。在本例使用的Schema中,有精装、平装、电子书等图书格式。因此,在生成的代码中,这些值可以通过enum获得:

ex_class_BookFormatType

要将枚举值分配给对象,请使用如下代码:

 

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

 

您可以按如下方式从XML实例文档中读取此类枚举值:

 

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

 

当“if”条件不充分时,创建一个开关以获取每个枚举值并根据需要对其进行处理。

 

使用xs:dateTime和xs:duration类型

如果您从中生成代码的Schema使用时间和持续时间类型,例如xs:dateTimexs:duration,这些将在生成的代码中转换为Altova本机类。因此,要将日期或持续时间值写入XML文档,请执行以下操作:

 

1.构造一个Altova.Types.DateTimeAltova.Types.Duration对象(来自System.DateTime,或使用小时和分钟等部分。有关更多信息,请参见Altova.Types.DateTimeAltova.Types.Duration)。

2.将对象设为所需元素或特性的值,例如:

 

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

 

要从XML文档读取日期或持续时间,请执行以下操作:

 

1.将元素值(或特性)声明为Altova.Types.DateTimeAltova.Types.Duration对象。

2.对所需的元素或特性进行格式设置,例如:

 

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

 

有关更多信息,请参见Altova.Types.DateTimeAltova.Types.Duration类引用。

 

使用派生类型

如果您在XML Schema中定义了派生类型,则可以在以编程方式创建或加载的XML文档中保留类型派生。以本例中使用的Schema为例,以下代码片段展示了如何创建一个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();

 

请注意,为新创建的书设置xsi:type特性是很重要的。这确保了在验证XML文档时,Schema可以正确解释图书类型。

 

以下代码片段显示了当从XML文档加载数据时,如何在加载的XML实例中标识派生类型DictionaryType的图书。首先,代码找到图书节点的xsi:type特性的值。如果此节点的命名空间URI是http://www.nanonull.com/LibrarySample,并且URI查找前缀和类型与xsi:type特性的值匹配,则它是一个字典:

 

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