[XML][C#.NET] 處理 ezTRACK 的 EPCIS Xml文件

ezTRACK 是一家全球性的RFID、條碼追蹤電子交換平台,然而EPCIS即是電子產品程式碼資訊服務(Electronic Product Code Information Services),為EPC資料提供了一整套標準介面,今天重點不是它們兩個,而是ezTRACK所給我的文件,我要批次產生文件然後上傳到它們的Server,以下就是ezTrack的Xml文件範本:

<?xml version="1.0" encoding="utf-8"?>

<epcis:EPCISDocument xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sensor="http://epcis.gs1hk.org/ns/sensor" xmlns:gs1hk="urn:epcglobal:gs1hk:xsd:ext" schemaVersion="1" creationDate="2010-09-15T04:07:52" xmlns:epcis="urn:epcglobal:epcis:xsd:1">

  <EPCISBody>

    <EventList>

      <ObjectEvent>

        <eventTime>2011-12-25T17:04:52</eventTime>

        <eventTimeZoneOffset>+08:00</eventTimeZoneOffset>

        <epcList>

          <epc>BBAA99887766554400085172</epc>

          <epc>BBAA99887766554400085173</epc>

        </epcList>

        <action>OBSERVE</action>

        <bizStep>urn:epcglobal:fmcg:bizstep:Gate_In</bizStep>

        <bizLocation>

          <id>urn:epcglobal:fmcg:loc.MMMMM.202.MZMFG_Warehouse_Gate_Door,414.Gate_Door2</id>

        </bizLocation>

        <bizTransactionList>

          <bizTransaction type="urn:gs1hk:ext:order">China</bizTransaction>

        </bizTransactionList>

        <sensor:temperature>20.5</sensor:temperature>

        <sensor:state>Alram</sensor:state>

        <sensor:temperaturereporturl>http://www.gts-portal.co/Z/Page/TempChart.aspx?EPC=BBAA99887766554400085172&amp;Date=2011-12-25T17:04:52</sensor:temperaturereporturl>

      </ObjectEvent>

    </EventList>

  </EPCISBody>

</epcis:EPCISDocument>
 

一看到這個文件時,我就想要利用XSD.exe來處理(請參考[XML] XSD Convert XML),於是就去找它的schema快速處理http://www.epcglobalinc.org/standards/epcis/epcis_1_0-schema-20070412.zip,但一直沒有辦法成功,兩岸三地的高手都說xsd檔有問題

http://social.msdn.microsoft.com/Forums/zh-TW/239/thread/8e62987a-1e67-4feb-8856-ee801ee2baa2

http://social.msdn.microsoft.com/Forums/zh-TW/xmlwebserviceszhchs/thread/df0a2242-99bc-4097-9d79-1a28ed089f53

於是乎動手自己寫Entity Class來序列化為Xml念動便油然而生,這得定義Xml Attribute,我們先拆成小塊處理,雖然實作過程有碰到些問題,但總算解決了。


首先是bizLocation區塊的定義,我猜想id結構應該會是集合,所以用List<string>

image

 

/// <summary>

/// 位置

/// </summary>

[Serializable, XmlRoot("bizLocation")]

public class BizLocation

{

    /// <summary>

    /// 位置ID

    /// </summary>

    private List<string> _Ids= new List<string>();

    [XmlElement("id")]

    public List<string> Ids

    {

        get { return _Ids; }

        set { _Ids = value; }

    }

}
  
    

epcList我則是指定XmlArrayItem屬性,這跟上述bizLocation屬性最後產生的結果會一樣

image 

 

private List<string> _epcList = new List<string>();

/// <summary>

/// EPC 編號清單

/// EPC List

/// </summary>

[XmlArrayItem("epc")]

public List<string> epcList

{

    get { return this._epcList; }

    set { this._epcList = value; }

}


bizTransaction裡有XmlAttribute type,所以要特別處理下,Content則是用來裝BizTransaction用

image

/// <summary>

/// 交易內容

/// </summary>

[Serializable, XmlRoot("bizTransaction")]

//[Serializable]

public class BizTransaction

{

    private string _type = "urn:gs1hk:ext:order";

    /// <summary>

    /// 交易內容屬性

    /// </summary>

    [XmlAttribute("type")]

    public string type

    {

        get { return this._type; }

        set { this._type = value; }

    }

    /// <summary>

    /// 內容

    /// </summary>

    [XmlText()]

    public string Content { get; set; }

}
  
    

sensor 指的是xml的命名空間,所以需要為這些屬性定義Namespace

image 

 

/// <summary>

/// Tag 溫度

/// </summary>

[XmlElement("temperature", Namespace = "http://epcis.gs1hk.org/ns/sensor")]

public string Temperature { get; set; }



/// <summary>

/// Tag 的狀態

/// </summary>

[XmlElement("state", Namespace = "http://epcis.gs1hk.org/ns/sensor")]

public string State { get; set; }



/// <summary>

/// temperaturereporturl 超連結

/// </summary>

[XmlElement("temperaturereporturl", Namespace = "http://epcis.gs1hk.org/ns/sensor")]

public string TemperaturerEportUrl { get; set; }

 
   

整個ObjectEvent結構在類別裡的定義如下:

image

 

/// <summary>

/// 事件類型

/// </summary>

/// <seealso cref="ObjectEvent"/>

[Serializable, XmlRoot("ObjectEvent")]

public class ObjectEvent

{

    #region 固定欄位



    #region EventTime

    /// <summary>

    /// Tag 當時的時間

    /// Event Time

    /// </summary>

    [XmlElement("eventTime")]

    public string EventTime { get; set; }

    #endregion



    #region EventTimeZoneOffset

    /// <summary>

    /// Time Zone offset

    /// 時差

    /// </summary>

    [XmlElement("eventTimeZoneOffset")]

    public string EventTimeZoneOffset { get; set; }



    #endregion



    #region epcList

    private List<string> _epcList = new List<string>();

    /// <summary>

    /// EPC 編號清單

    /// EPC List

    /// </summary>

    [XmlArrayItem("epc")]

    public List<string> epcList

    {

        get { return this._epcList; }

        set { this._epcList = value; }

    }

    #endregion



    #region action

    /// <summary>

    /// 事件動作

    /// Action

    /// </summary>

    [XmlElement("action")]

    public string EventAction { get; set; }

    #endregion



    #region bizStep

    /// <summary>

    /// 商業流程

    /// BizStep

    /// </summary>

    [XmlElement("bizStep")]

    public string BizStep { get; set; }

    #endregion



    #region disposition

    /// <summary>

    /// 目前配置

    /// Disposition

    /// </summary>

    [XmlElement("disposition")]

    public string Disposition { get; set; }

    #endregion



    #region bizLocation

    private BizLocation _BizLocation = new BizLocation();

    /// <summary>

    /// 位置

    /// bizLocation

    /// </summary

    [XmlElement("bizLocation")]

    public BizLocation BizLocation

    {

        get { return this._BizLocation; }

        set { this._BizLocation = value; }

    }



    #endregion



    #region bizTransaction



    private BizTransactionList _BizTransactionList = new BizTransactionList();

    /// <summary>

    /// 交易清單

    /// </summary>

    [XmlElement("bizTransactionList")]

    public BizTransactionList BizTransactionList

    {

        get { return this._BizTransactionList; }

        set { this._BizTransactionList = value; }

    }

    #endregion



    #endregion



    #region 可擴充欄位

    /// <summary>

    /// Tag 溫度

    /// </summary>

    [XmlElement("temperature", Namespace = "http://epcis.gs1hk.org/ns/sensor")]

    public string Temperature { get; set; }



    /// <summary>

    /// Tag 的狀態

    /// </summary>

    [XmlElement("state", Namespace = "http://epcis.gs1hk.org/ns/sensor")]

    public string State { get; set; }



    /// <summary>

    /// temperaturereporturl 超連結

    /// </summary>

    [XmlElement("temperaturereporturl", Namespace = "http://epcis.gs1hk.org/ns/sensor")]

    public string TemperaturerEportUrl { get; set; }

    #endregion

}


接著是ObjectEvent上層EventList

image

/// <summary>

/// 事件清單

/// </summary>

[Serializable, XmlRoot("EventList")]

public class EventList

{

    private ObjectEvent _ObjectEvent = new ObjectEvent();

    /// <summary>

    /// 事件類型

    /// </summary>

    [XmlElement("ObjectEvent")]

    public ObjectEvent ObjectEvent

    {

        get { return this._ObjectEvent; }

        set { this._ObjectEvent = value; }

    }

}


還有EventList的上層EPCISBody

image

/// <summary>

/// EPCIS 內文

/// </summary>

[Serializable, XmlRoot("EPCISBody")]

public class Body

{

    EventList _EventList = new EventList();

    /// <summary>

    /// 事件清單

    /// </summary>

    [XmlElement("EventList")]

    public EventList EventList

    {

        get { return this._EventList; }

        set { this._EventList = value; }

    }

}


EPCISBody的上層EPCISDocument

image 

/// <summary>

/// EPCIS Root

/// </summary>

[Serializable, XmlRoot("EPCISDocument", Namespace = "urn:epcglobal:epcis:xsd:1")]

public class EPCISDocument

{

    private Body _EPCISBody = new Body();

    /// <summary>

    /// EPCIS 內容

    /// </summary>

    [XmlElement(ElementName = "EPCISBody", Namespace = "")]

    public Body EPCISBody

    {

        get { return this._EPCISBody; }

        set { this._EPCISBody = value; }

    }



    private decimal _SchemaVersion = (decimal)1.0;

    /// <summary>

    /// 結構版本

    /// </summary>

    [XmlAttribute("schemaVersion")]

    public decimal SchemaVersion

    {

        get { return this._SchemaVersion; }

        set { this._SchemaVersion = value; }

    }

    private string _CreationDate = "2010-09-15T04:07:52";

    /// <summary>

    /// 認証日期

    /// </summary>

    [XmlAttribute("creationDate")]

    public string CreationDate

    {

        get { return this._CreationDate; }

        set { this._CreationDate = value; }

    }

}

 

剛剛我們在一些屬性定義了Xml Namespace,如下圖:

image

還要設定XmlSerializerNamespaces 類別,等會序列化時會用的到

XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();

namespaces.Add("epcis", "urn:epcglobal:epcis:xsd:1");

namespaces.Add("sensor", "http://epcis.gs1hk.org/ns/sensor");

namespaces.Add("gs1hk", "urn:epcglobal:gs1hk:xsd:ext");

namespaces.Add("xsi", http://www.w3.org/2001/XMLSchema-instance);



然後再為這些欄位定義一個Config類別,用它來對外公開主要設定結構欄位有哪些

/// <summary>

/// EPSIC設定檔

/// </summary>

[Serializable]

public class EPCISConfig

{

    #region FileName

    /// <summary>

    /// 完整檔案路徑

    /// </summary>

    public string FileName { get; set; }

    #endregion



    #region EventTime

    private DateTime? _EventTime = null;

    /// <summary>

    /// UTC時間

    /// </summary>

    public DateTime? EventTime

    {

        get

        {

            //if (this._EventTime == null)

            //    this._EventTime = DateTime.Now;



            return this._EventTime;

        }

        set { this._EventTime = value; }

    }

    #endregion



    #region EventTimeZoneOffset

    private string _EventTimeZoneOffset = null;

    /// <summary>

    /// 時差

    /// </summary>

    public string EventTimeZoneOffset

    {

        get

        {

            if (string.IsNullOrEmpty(this._EventTimeZoneOffset))

            {

                int day = TimeZoneInfo.Local.BaseUtcOffset.Days;



                int hours = TimeZoneInfo.Local.BaseUtcOffset.Hours;

                int minutes = TimeZoneInfo.Local.BaseUtcOffset.Minutes;

                string localZone = "";

                if (hours > 0)

                    localZone = string.Format("+{0}:{1}", hours.ToString().PadLeft(2, '0'), minutes.ToString().PadLeft(2, '0'));

                else if (hours < 0)

                    localZone = string.Format("-{0}:{1}", hours.ToString().PadLeft(2, '0'), minutes.ToString().PadLeft(2, '0'));

                this._EventTimeZoneOffset = localZone;

            }

            return this._EventTimeZoneOffset;

        }

        set { this._EventTimeZoneOffset = value; }

    }

    #endregion



    #region EpcList

    private List<string> _EpcList = new List<string>();

    /// <summary>

    /// EPC 清單

    /// </summary>

    public List<string> EpcList

    {

        get { return this._EpcList; }

        set { this._EpcList = value; }

    }

    #endregion



    #region Action

    private string _Action;

    /// <summary>

    /// 事件動作

    /// Action

    /// </summary>

    public string Action

    {

        get { return this._Action; }

        set { this._Action = value; }

    }

    #endregion



    #region BizStep

    /// <summary>

    /// 商業流程

    /// </summary>

    public string BizStep { get; set; }

    #endregion



    #region Disposition

    /// <summary>

    /// 目前配置

    /// </summary>

    public string Disposition { get; set; }

    #endregion



    #region BizTransactionList



    private List<string> _TransactionList = new List<string>();

    /// <summary>

    /// 交易清單

    /// </summary>

    public List<string> TransactionList

    {

        get { return this._TransactionList; }

        set { this._TransactionList = value; }

    }

    #endregion



    #region LocationList

    private List<string> _LocationList = new List<string>();

    /// <summary>

    /// 位置清單

    /// </summary>

    public List<string> LocationList

    {

        get { return _LocationList; }

        set { _LocationList = value; }

    }

    #endregion



    #region 擴充欄位

    #region CurrentTemperature

    /// <summary>

    /// 目前時間

    /// </summary>

    public string Temperature { get; set; }

    #endregion



    #region CurrentState

    /// <summary>

    /// 目前狀態

    /// </summary>

    public string State { get; set; }

    #endregion



    #region TemperatureURL

    /// <summary>

    /// 溫度查詢網址

    /// </summary>

    public string TemperatureURL { get; set; }

    #endregion



    #endregion

}


Document工廠類別則是用來實體化EPCISDocument 以及建立實體Xml檔案

public class Document

{

    public Document(EPCISConfig Config)

    {

        if (Config == null)

            throw new ArgumentNullException("Config");

        if (string.IsNullOrEmpty(Config.FileName))

            throw new ArgumentNullException("Config.FileName");



        XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();

        namespaces.Add("epcis", "urn:epcglobal:epcis:xsd:1");

        namespaces.Add("sensor", "http://epcis.gs1hk.org/ns/sensor");

        namespaces.Add("gs1hk", "urn:epcglobal:gs1hk:xsd:ext");

        namespaces.Add("xsi", "http://www.w3.org/2001/XMLSchema-instance");

        EPCISDocument doc = this.createEpcIsDocument(Config);

        this.ToXml(Config.FileName, doc, namespaces);

    }

    EPCISDocument createEpcIsDocument(EPCISConfig Config)

    {

        EPCISDocument epcisDocument = new EPCISDocument();

        string eventTime = string.Format("{0:s}", (DateTime)Config.EventTime);

        epcisDocument.EPCISBody.EventList.ObjectEvent.EventTime = eventTime;

        epcisDocument.EPCISBody.EventList.ObjectEvent.EventTimeZoneOffset = Config.EventTimeZoneOffset;

        epcisDocument.EPCISBody.EventList.ObjectEvent.epcList = Config.EpcList;

        epcisDocument.EPCISBody.EventList.ObjectEvent.EventAction = Config.Action;

        epcisDocument.EPCISBody.EventList.ObjectEvent.BizStep = Config.BizStep;

        epcisDocument.EPCISBody.EventList.ObjectEvent.Disposition = Config.Disposition;

        epcisDocument.EPCISBody.EventList.ObjectEvent.BizLocation.Ids = Config.LocationList;

        foreach (var item in Config.TransactionList)

        {

            epcisDocument.EPCISBody.EventList.ObjectEvent.BizTransactionList.BizTransaction.Add(new BizTransaction() { Content = item });

        }



        epcisDocument.EPCISBody.EventList.ObjectEvent.State = Config.State;

        epcisDocument.EPCISBody.EventList.ObjectEvent.Temperature = Config.Temperature;

        epcisDocument.EPCISBody.EventList.ObjectEvent.TemperaturerEportUrl = Config.TemperatureURL;

        return epcisDocument;

    }

    void ToXml(string FileName, object Object, XmlSerializerNamespaces Namespace)

    {

        XmlSerializer xml = null;

        Stream stream = null;

        StreamWriter writer = null;

        try

        {

            xml = new XmlSerializer(Object.GetType());

            stream = new FileStream(FileName, FileMode.Create, FileAccess.Write, FileShare.Read);

            writer = new StreamWriter(stream, Encoding.UTF8);

            xml.Serialize(writer, Object, Namespace);

        }

        catch

        {

            throw;

        }

        finally

        {

            if (writer != null)

                writer.Close();

            if (stream != null)

                stream.Close();

        }

    }

}


在客戶端,定義EPCISConfig ,並實體化Document 即可

private void button1_Click(object sender, EventArgs e)

{

    string file = Application.StartupPath + "\\" + "Test.xml";

    EPCISConfig config = new EPCISConfig();



    DateTime date = DateTime.Now.ToUniversalTime();

    string time = string.Format("{0:s}", (DateTime)date);

    string epc = "BBAA99887766554400085172";

    config.FileName = file;

    //實體化Config並帶入相關欄位

    config.BizStep = "urn:epcglobal:fmcg:bizstep:Gate_In";

    config.State = "Alram";

    config.Action = "OBSERVE";

    config.Temperature = "20.5";

    config.EventTime = date;

    config.LocationList.Add("urn:epcglobal:fmcg:loc.MMMMM.202.MZMFG_Warehouse_Gate_Door,414.Gate_Door2");

    string url = string.Format("http://www.gts-portal.co/Z/Page/TempChart.aspx?EPC={0}&Date={1}", epc, time);

    config.TemperatureURL = url;

    config.EpcList.Add(epc);

    config.EpcList.Add("BBAA99887766554400085173");



    config.TransactionList.Add("China");



    Document doc = new Document(config);



}


在實作這個Xml時我有碰到一些問題,這些問題我在半年多前就已經透過MSDN論壇解決,感謝兩岸三地的高手協助,今日特與分享實作結果

http://social.msdn.microsoft.com/Forums/zh-TW/239/thread/2c8d5930-e5ea-4f6a-8987-f19bd589af22

http://social.msdn.microsoft.com/Forums/zh-TW/xmlwebserviceszhchs/thread/4809cf9e-fb53-42f7-98c5-8b77ca0b2d92

範例下載:

System.ezTrack.Xml.zip


你可能感兴趣的:(.net)