定义一个接口,包含两个方法:实体转xml 和 xml转实体。包含一个属性根节点标签名称
/// <summary> /// 定义元属性实体类与Xml之间的转换接口 /// </summary> /// <typeparam name="T">元属性实体类</typeparam> public interface IEntitySerialization<T> { /// <summary> /// 将实体类<c>T</c>使用<see cref="XmlWriter"/>转为XML 数据写到流、文件、文本 /// 读取器或字符串。 /// </summary> /// <param name="writer"><see cref="XmlWriter"/>实例</param> void WriteXml(XmlWriter writer); /// <summary> /// 将<see cref="XmlNode"/>节点的信息转为实体类<c>T</c> /// </summary> /// <param name="node"><see cref="XmlNode"/>实例,该实例包含了<c>T</c> /// 实体类所需要的信息</param> /// <returns>实体类<c>T</c></returns> T GetObject(XmlNode node); /// <summary> /// 根节点元素标签名称 /// </summary> string RootElementName { get; } }
定义xml对应的实体,实体都继承上面的接口
并实现具体实体对应的xml和实体之间的转化方式
public class Hape : IEntitySerialization<Hape > { /// <summary> /// 名称 /// </summary> public string Name { get; set; } /// <summary> /// 空间坐标 WKT格式 /// </summary> public string Geometry { get; set; } /// <summary> /// 实体转xml /// </summary> /// <param name="writer"></param> public void WriteXml(XmlWriter writer) { writer.WriteStartElement(this.RootElementName); XmlHelper.WriteOptionalAttribute(writer,"name",Name); XmlReader reader = XmlReader.Create(new StringReader(DbGeography.FromText(Geometry).AsGml())); var gml = Deserialize(reader); Serialize(writer,gml); writer.WriteEndElement(); } /// <summary> /// xml转实体 /// </summary> /// <param name="node"></param> /// <returns></returns> public Hape GetObject(XmlNode node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (node.Name != this.RootElementName) { throw new ArgumentException("The element name of node is not " + RootElementName); } var name = XmlHelper.GetOptionalAttributeValue(node,"name"); var gml = node.InnerXml.Replace("gml:","").Replace(":gml",""); var geometry = DbGeography.FromGml(gml).AsText(); return new Shape { Name = name,Geometry = geometry }; } /// <summary> /// 根节点标签名称 /// </summary> public string RootElementName => "Hape"; }
一个节点可以包含多个节点的集合
/// <summary> /// 集合 /// </summary> public class HapeCollection : List<Hape>,IEntitySerialization<HapeCollection> { /// <summary> /// 实体转xml /// </summary> /// <param name="writer"></param> public void WriteXml(XmlWriter writer) { writer.WriteStartElement(this.RootElementName); XmlHelper.WriteEntityCollection(writer,this); writer.WriteEndElement(); } /// <summary> /// xml转实体 /// </summary> /// <param name="node"></param> /// <returns></returns> public HapeCollection GetObject(XmlNode node) { var result = new HapeCollection(); var shapeList = XmlHelper.GetEntityCollection<Shape>(node,new hape().RootElementName); result.AddRange(shapeList); return result; } /// <summary> /// 根节点标签名称 /// </summary> public string RootElementName => "Hapes"; }
当每个实体都实现了xml和实体之间的转化,就很容易将这些实体组合成一个复杂的实体,并且转化方法可以很简单。
下面进行测试查看
给hapeCollection 赋值
var hape = new Hape() { Name = "口",Geometry = "POINT(4 6)" }; var hape2 = new Hape() { Name = "地",Geometry = "LINESTRING(47 -122.36 47 -122.343)" }; var hape3 = new Hape() { Name = "造",Geometry = "POLYGON ((36 108 391 10 36 108 36 108 361 108))" }; Hapes.Add(hape3); Hapes.Add(hape2); Hapes.Add(hape);调用该实体的方法 ,转化成xml
public void TestHapeCollection() { var result = ""; using (MemoryStream ms = new MemoryStream()) { using (XmlWriter writer = XmlHelper.GetXmlWriter(ms)) { Shapes.WriteXml(writer); } result = Encoding.UTF8.GetString(ms.ToArray()); var obj = GetObject<HapeCollection>(result); } }
最后得到的xml结果为
<Hapes> <Hape name="造"> <gml:Polygon> <gml:exterior> <gml:LinearRing> <gml:posList>36 108 391 10 36 108 36 108 361 108</gml:posList> </gml:LinearRing> </gml:exterior> </gml:Polygon> </Hape> <Hape name="地"> <gml:LineString"> <gml:posList>47 -122.36 47 -122.343</gml:posList> </gml:LineString> </Hape> <Hape name="口"> <gml:Point> <gml:pos>6 4</gml:pos> </gml:Point> </Hape> </Hapes>也可以将上面的xml转化成其对应的实体。