从示例Schema生成代码后,将生成一个测试C#应用程序以及多个支持的Altova库。
关于生成的C#库
生成的代码的中心类是Doc2类,它表示XML文档。为每个Schema生成这样的类,其名称取决于Schema文件名。请注意,将此类命名为Doc2以避免可能与命名空间名称发生冲突。如图所示,此类提供了从文件、二进制流或字符串中加载文档(或将文档保存到文件、流和字符串)的方法。有关此类的描述,请参见类引用([YourSchema].[Doc] )。
Doc2类的Library成员表示文档的实际根。
根据关于Schema包装库(C#)中的代码生成规则,将为特定类型的每个特性和元素生成成员类。在生成的代码中,此类成员类的名称将分别以MemberAttribute_和MemberElement_为前缀。此类的示例是MemberAttribute_ID和MemberElement_Author,它们分别从图书的Author元素和ID特性生成(在下图中,它们是嵌套在BookType下的类)。它们允许您对XML实例文档中的相应元素和特性进行编程操作(例如追加、删除、设置值等)。有关更多信息,请参见[YourSchemaType].MemberAttribute and [YourSchemaType].MemberElement类引用。
由于DictionaryType是一个复杂类型,从Schema中的BookType派生,因此这一关系也反映在生成的类中。如下图所示,DictionaryType类继承了BookType类。
如果简单类型在您的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获得:
要将枚举值分配给对象,请使用如下代码:
// 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:dateTime或xs:duration,这些将在生成的代码中转换为Altova本机类。因此,要将日期或持续时间值写入XML文档,请执行以下操作:
1.构造一个Altova.Types.DateTime或Altova.Types.Duration对象(来自System.DateTime,或使用小时和分钟等部分。有关更多信息,请参见Altova.Types.DateTime和Altova.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.DateTime或Altova.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.DateTime和Altova.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"); } } |