读取/写入由 XSD 定义的 XML 文件





5.00/5 (1投票)
如何快速生成代码来处理带有 XSD 定义的 XML 文件
引言
网上有很多文章展示了如何序列化/反序列化 XML - 有些不错,但大多数只是重复基本内容。我在这里不会这样做。几乎没有人介绍在您拥有 XSD 定义文件的情况下如何快速完成此操作。
这里有一个 Github 仓库 伴随本文。
为了演示这个过程,我们将导入 GPX 文件。这些是具有 gpx 扩展名的 XML 格式的文件。详细的 XSD 定义在这里。
只需看一眼定义,您就能知道 GPX 文件可以有多复杂和详细,以及手动编写和测试处理类需要多少精力。幸运的是,微软提供了一个鲜为人知的工具来自动化大部分过程,它隐藏在 Windows SDK 中 - XSD.exe。
构建类
- 设置一个基本的 DotNetCore 控制台项目(如果您使用 Visual Studio,IDE 将为您执行一些巧妙的 XSD 到类关联)。
- 获取 XSD 文件并将其添加到子文件夹 - GPX.xsd - 在这种情况下是 Gpx。
- 找到 XSD.exe。它位于 Windows SDK 中 - 目前在我的机器上位于 C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools。
- 打开一个控制台/powershell 窗口,并切换到 XSD.exe 目录。
- 运行 XSD.exe 针对 xsd 文件。请注意,我已将输出设置为输入目录。
.\xsd.exe "D:\Documents\GitHub\GPXReader\Gpx\gpx.xsd"
/c /outputdir:"D:\Documents\GitHub\GpxReader\Gpx"
结果应该是(我添加了分隔符 ============= 以使其更清晰)
PS C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools>
.\xsd.exe "D:\Documents\GitHub\GPXReader\Gpx\gpx.xsd"
/c /outputdir:"D:\Documents\GitHub\GPXReader\Gpx"
==========================================================
Microsoft (R) Xml Schemas/DataTypes support utility
[Microsoft (R) .NET Framework, Version 4.8.3928.0]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'D:\Documents\GitHub\GPXReader\Gpx\gpx.cs'.
===========================================================
PS C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools>
在项目中,您现在应该看到
不要被诱惑去重命名(我也不喜欢那些类名!)。考虑一下如果定义被更新,您的代码维护过程会怎样。
导入代码
现在我们需要一个简单的 Importer 类来展示我们正在正确导入数据。这些方法都是 static
,并使用流,因为 XmlSerializer
使用流,而不是字符串。
ReadFile
- 有两个版本
- 创建一个
StreamReader
来获取导入文件 - 创建一个
XmlSerializer
对象,并使用正确的对象类型和 XSD 定义 - 运行
Deserialise
,将结果转换为正确的对象类型 - 对象处置由
using
处理
WriteFile
:
- 创建一个
StreamWriter
来接受XmlSerializer
输出 - 指向输出文件 - 创建一个
XmlSerializer
对象,并使用正确的对象类型和 XSD 定义 - 运行
Serialize
,输出到StreamWriter
- 刷新
StreamWriter
以将数据写入文件 - 对象处置由
using
处理
using System;
using System.IO;
using System.Xml.Serialization;
namespace GPXReader
{
public class GPXReader
{
public static gpxType ReadFile(Uri url)
{
gpxType gpxdata = null;
try
{
using (StreamReader reader = new StreamReader(url.AbsolutePath))
{
XmlSerializer serializer = new XmlSerializer(typeof(gpxType),
"http://www.topografix.com/GPX/1/1");
gpxdata = serializer.Deserialize(reader) as gpxType;
}
}
catch (Exception e)
{
Console.WriteLine($"An Error has occurred accessing file
{url.AbsolutePath}.{Environment.NewLine} Details:{Environment.NewLine}
{e.StackTrace}.");
}
return gpxdata;
}
// Bool return version
public static bool ReadFile(Uri url, out gpxType gpxdata)
{
gpxdata = null;
try
{
using (StreamReader reader = new StreamReader(url.AbsolutePath))
{
XmlSerializer serializer = new XmlSerializer(typeof(gpxType),
"http://www.topografix.com/GPX/1/1");
gpxdata = serializer.Deserialize(reader) as gpxType;
return true;
}
}
catch (Exception e)
{
Console.WriteLine($"An Error has occurred accessing file
{url.AbsolutePath}.{Environment.NewLine}
Details:{Environment.NewLine} {e.StackTrace}.");
}
return false;
}
public static bool WriteFile(gpxType data, Uri url)
{
try
{
using (StreamWriter writer = new StreamWriter(url.AbsolutePath, false))
{
XmlSerializer serializer = new XmlSerializer(typeof(gpxType),
"http://www.topografix.com/GPX/1/1");
serializer.Serialize(writer, data);
writer.Flush();
return true;
}
}
catch (Exception e)
{
Console.WriteLine($"An Error has occurred accessing file
{url.AbsolutePath}.{Environment.NewLine}
Details:{Environment.NewLine} {e.StackTrace}.");
}
return false;
}
}
}
最后,我们构建一个简单的 Program
。我将一个相当复杂的 gpx 文件(从 Google Maps 导入)添加到项目中。
using System;
namespace GPXReader
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("GPX Reader");
var data = GPXReader.ReadFile
(new Uri($"D:/Documents/GitHub/GPXReader/gpx/Test.gpx"));
Console.WriteLine($"Read file");
// Set Break point here to view the imported file
Console.WriteLine($"Writing output file");
GPXReader.WriteFile
(data, new Uri($"D:/Documents/GitHub/GPXReader/gpx/output.gpx"));
Console.WriteLine("Complete");
}
}
}
项目如下所示
测试输出
使用断点运行项目,并探索创建的 data
对象。
就是这样!
历史
- 2020 年 12 月 1 日:初始版本