定義一個接口,包含兩個方法:實體轉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轉化成其對應的實體。