
命名空间
作为一种归纳方式,便于后续命名空间的快速引入。
cs
/// <summary>
/// 定义 命名空间常量
/// </summary>
public static class WpmlNamespace
{
public const string Wpml = "http://www.dji.com/wpmz/1.0.2";
public const string Kml = "http://www.opengis.net/kml/2.2";
}
根节点
使用[XmlRoot] 、自定义根节点属性[XmlAttribute]以及配置子节点[XmlElement]。
cs
[XmlRoot("kml", Namespace = WpmlNamespace.Kml)]
public class KmlRoot
{
[XmlElement("Document", Namespace = WpmlNamespace.Kml)]
public Document Document { get; set; }
[XmlAttribute("wpml", Namespace = "http://www.w3.org/2000/xmlns/")]
public string WpmlNamespaceAttribute { get; set; } = WpmlNamespace.Wpml;
}
子节点类型
使用[XmlElement] 特性,进行子节点序列名称以及对应的命名空间。
cs
//[XmlType("Document", Namespace = WpmlNamespace.Kml)]
public class Document
{
// 创建信息 (Document的子元素)
[XmlElement("author", Namespace = WpmlNamespace.Wpml)]
public string Author { get; set; } // 非必需
[XmlElement("createTime", Namespace = WpmlNamespace.Wpml)]
public long? CreateTime { get; set; } // 非必需, ms 时间戳
[XmlElement("updateTime", Namespace = WpmlNamespace.Wpml)]
public long? UpdateTime { get; set; } // 非必需, ms 时间戳
}
填充数据
逐步构建实例数据,用于后续查看序列化效果。
cs
// 创建KML内容的逻辑
KmlRoot kmlRoot = new KmlRoot();
// Document 节点
Document document = new Document();
kmlRoot.Document = document;
document.CreateTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
document.UpdateTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
序列化输出
使用XmlSerializer,XmlWriterSettings,StringWriter以及XmlWriter生成序列数据。
cs
// 构建序列化实例
var serializer = new XmlSerializer(typeof(KmlRoot), null,null, null,null);
var settings = new XmlWriterSettings // 序列化配置
{
Indent = true, // 启用自定义间隔
IndentChars = " ",// 属性间隔
Encoding = Encoding.UTF8,// 设置编码格式
OmitXmlDeclaration = false, // 保持 XML 声明
};
using (var stringWriter = new System.IO.StringWriter())
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
// 序列化对象
serializer.Serialize(xmlWriter, kmlRoot);
// 获取序列化后的字符串
var xmlString = stringWriter.ToString();
return xmlString;
}
序列化结果如下:
xml
<?xml version="1.0" encoding="utf-16"?>
<kml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wpml="http://www.dji.com/wpmz/1.0.2" xmlns="http://www.opengis.net/kml/2.2">
<Document>
<wpml:createTime>1761753196268</wpml:createTime>
<wpml:updateTime>1761753196269</wpml:updateTime>
</Document>
</kml>
修改xml声明
可以看到序列化输出结果中,当前文本的文本编码说明为UTF-16,实际需要的是UTF-8,原始文本编码和目标编码如下。
原始文本编码。
xml
<?xml version="1.0" encoding="utf-16"?>
目标文本编码。
xml
<?xml version="1.0" encoding="utf-8"?>
解决办法是继承StringWriter 类,重写编码属性。
cs
// 设置文本编码为utf-8
public class Utf8StringWriter: System.IO.StringWriter
{
public override Encoding Encoding => Encoding.UTF8;
}
替换序列化代码中的StringWriter 实例构造。
cs
//using (var stringWriter = new StringWriter())
using (var stringWriter = new Utf8StringWriter())
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
// 序列化对象
serializer.Serialize(xmlWriter, kmlRoot);
// 获取序列化后的字符串
var xmlString = stringWriter.ToString();
return xmlString;
}
输出结果如下:
xml
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wpml="http://www.dji.com/wpmz/1.0.2" xmlns="http://www.opengis.net/kml/2.2">
<Document>
<wpml:createTime>1761753196268</wpml:createTime>
<wpml:updateTime>1761753196269</wpml:updateTime>
</Document>
</kml>
xml大写声明编码值
当前小写编码值:
xml
<?xml version="1.0" encoding="utf-8"?>
期望大写编码值:
xml
<?xml version="1.0" encoding="UTF-8"?>
自定义UTF8Encoding编码类。
cs
/// <summary>
/// 自定义大写的 UTF8Encoding
/// </summary>
public class CustomUTF8Encoding : UTF8Encoding
{
public override string HeaderName => base.HeaderName.ToUpper();
public override string WebName => base.WebName.ToUpper();
public override string BodyName => base.BodyName.ToUpper();
}
修改Utf8StringWriter类代码。
cs
public class Utf8StringWriter: System.IO.StringWriter
{
public Utf8StringWriter()
{
}
public override Encoding Encoding => new CustomUTF8Encoding();
}
不显示默认值属性
对于未赋值字段,默认会显示并标记为xsi:nil="true",这在某些场景并不合适,需要进行去除。
xml
<?xml version="1.0" encoding="utf-8"?>
<kml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wpml="http://www.dji.com/wpmz/1.0.2" xmlns="http://www.opengis.net/kml/2.2">
<Document>
<wpml:createTime>1761899701431</wpml:createTime>
<wpml:updateTime>1761899701431</wpml:updateTime>
<wpml:missionConfig>
<wpml:executeRCLostAction xsi:nil="true" />
<wpml:takeOffSecurityHeight>0</wpml:takeOffSecurityHeight>
<wpml:takeOffRefPointAGLHeight xsi:nil="true" />
<wpml:globalTransitionalSpeed>0</wpml:globalTransitionalSpeed>
<wpml:globalRTHHeight xsi:nil="true" />
</wpml:missionConfig>
</Document>
</kml>
对应属性修改为完整属性。
cs
private double? takeOffRefPointAGLHeight;
[XmlElement("takeOffRefPointAGLHeight", Namespace = WpmlNamespace.Wpml)]
public double? TakeOffRefPointAGLHeight { get => takeOffRefPointAGLHeight; set => takeOffRefPointAGLHeight = value; } // 非必需, m
添加函数public bool ShouldSerialize[对应的属性名称](),此处属性为TakeOffRefPointAGLHeight对应函数如下。函数内部实际按照需求进行判定,返回false则表示序列化中不显示,反之亦然。
cs
public bool ShouldSerializeTakeOffRefPointAGLHeight() => takeOffRefPointAGLHeight.HasValue;
去除自带命名空间
去除默认xml 中命名空间,如:xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"以及 xmlns:xsd="http://www.w3.org/2001/XMLSchema"。
xml
<kml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wpml="http://www.dji.com/wpmz/1.0.2" xmlns="http://www.opengis.net/kml/2.2">
</kml>
期望输出:
xml
<kml xmlns:wpml="http://www.dji.com/wpmz/1.0.2" xmlns="http://www.opengis.net/kml/2.2">
</kml>
可以尝试使用XmlSerializerNamespaces 序列化时,进行命名空间置空。
cs
//using (var stringWriter = new StringWriter())
using (var stringWriter = new Utf8StringWriter())
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
var namespaces = new XmlSerializerNamespaces();
namespaces.Add("", ""); // 添加空命名空间
// 序列化对象
serializer.Serialize(xmlWriter, kmlRoot,namespaces);
// 获取序列化后的字符串
var xmlString = stringWriter.ToString();
return xmlString;
}
序列化如下:
xml
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns:wpml="http://www.dji.com/wpmz/1.0.2" xmlns="http://www.opengis.net/kml/2.2">
<Document>
</Document>
</kml>
节点子类替换父类
使用过程中,多类型嵌套时,部分节点存在之类,需要在序列化时进行替换,此时需要引入XmlAttributeOverrides,在构造序列化实例时进行类型重写。
父类类型。
cs
public class ActionActuatorFuncParam
{
}
子类类型。
cs
public class OrientedShoot : ActionActuatorFuncParam
{
[XmlElement("focusX", Namespace = WpmlNamespace.Wpml)]
public int FocusX { get; set; } // 必需
}
public class GimbalRotate : ActionActuatorFuncParam
{
}
实际使用类。
cs
// KML 根元素
[XmlRoot("kml", Namespace = WpmlNamespace.Kml)]
public class KmlRoot
{
[XmlElement("Document", Namespace = WpmlNamespace.Kml)]
public Document Document { get; set; }
}
// 省略n级别嵌套类
[XmlType("action", Namespace = WpmlNamespace.Wpml)]
public class WpmlAction
{
[XmlElement("actionActuatorFuncParam", Namespace = WpmlNamespace.Wpml)]
public WpmlActionActuatorFuncParam ActionActuatorFuncParam { get; set; }
}
数据赋值。
cs
KmlRoot kmlRoot = new KmlRoot();
// 省略中间赋值
OrientedShoot actionActuatorFuncParam = new OrientedShoot();
action.ActionActuatorFuncParam = actionActuatorFuncParam;
actionActuatorFuncParam.FocusX = 12;// 进行属性赋值
进行重写设置。
cs
var attrs = new XmlAttributes();
var attr = new XmlElementAttribute("actionActuatorFuncParam", typeof(OrientedShoot)) { Namespace = WpmlNamespace.Wpml };
attrs.XmlElements.Add(attr);
// Adds the element to the collection of elements.
// Creates the XmlAttributeOverrides instance.
XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
// 指定需要替换类型的实际属性名称,不建议手动字符串拼写
attrOverrides.Add(typeof(WpmlAction), nameof(WpmlAction.ActionActuatorFuncParam), attrs);
//构建序列化实例(传入序列化化实例类型)
var serializer = new XmlSerializer(typeof(KmlRoot), overrides,null, new XmlRootAttribute("kml") { Namespace = WpmlNamespace.Kml },null);
var settings = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
Encoding = Encoding.UTF8,
OmitXmlDeclaration = false, // 保持 XML 声明
};
using (var stringWriter = new StringWriter())
using (var xmlWriter = XmlWriter.Create(stringWriter, settings))
{
// 序列化对象
serializer.Serialize(xmlWriter, kmlRoot);
// 获取序列化后的字符串
var xmlString = stringWriter.ToString();
return xmlString;
}
序列化结果如下:
xml
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:wpml="http://www.dji.com/wpmz/1.0.6">
<Document>
<Folder>
<Placemark>
<wpml:actionGroup>
<wpml:action>
<!--子类型序列化重写-->
<wpml:actionActuatorFuncParam>
<wpml:focusX>0</wpml:focusX>
</wpml:actionActuatorFuncParam>
<!--子类型序列化重写-->
</wpml:action>
</wpml:actionGroup>
</Placemark>
</Document>
</kml>