Makale Özeti

XML veri doğrulaması nedir? XML veri doğrulamasını koddan bağımsız olarak nasıl yaparız? DataRow nesnesini nasıl Serialise Deserialise yaparız? DTD ve XSD standartlarını nasıl kullanırız?

Makale

 

XML veri doğrulaması nedir? XML veri doğrulamasını koddan bağımsız olarak nasıl yaparız? DataRow nesnesini nasıl Serialise Deserialise yaparız?

Demo

         Farklı platformlar arasında veriyi taşımak için taşınan verinin modelini de bilmek gerekmektedir. XML veriyi ve veri modelini bir arada saklanması ve taşınması mantığından ortaya cıkmış bir standarttır. XML veri modelleme ve doğrulama için iki geçerli yolumuz var. Biri çok eski bir standart olan DTD standardıdır. Diğeri web servisler ile adını duyuran XSD standardıdır.

         XSD (XML Shema Definition) XML veri modelin doğrulanma ihtiyacından doğmuş olan ve ilk Microsoft tarafından duyurulan bir standarttır. Bilindiği üzere Typed DataSet sınıfları TypedDataSetGenerator sınıfı ile XSD dosyaları kullanılarak üretilen nesnelerdir.

         DTD (Data Type Definition) XSD benzeri bir XML tanımlama standardıdır. Avantajı XSD ye göre çok basit olması.  Eğer hız her şey ise sizin sisteminizde DTD veri doğrulamak için uygun bir  seçim olabilir. Özellikle eski sistemlerde (web servislerden önce) sıkça kullanılırdı. Eski platformlarda sadece DTD verisini test eden sınıflarımız vardı.  Eğer sizde benim gibi işiniz gereği eski platformları kullanan sistemler ile haberleşmek zorunda kalırsanız DTD doğrulama için Dispatcher sınıfı size yardımcı olacaktır.


         XML veriyi kontrol etmek için önce XmlResolver nesnesine veri doğrulama kaynağını vermemiz gerekmektedir. Bu uygulamada veri doğrulama kaynağını koddan bağımsız hale getirmek için veri doğrulama bilgisini dosyadan okuyacağız. Dosyadan okunan veri doğrulama bilgisi için önce XmlResolver sınıfından türetilene ve veri doğrulama şablonunu yerel dosyadan okuyacak bir sınıf yazmalıyız.

 

    #region local document type resolver

        /// <summary>

        /// XML Resolver için uygulama sınıfı

        /// </summary>

        internal class LocalDocumentTypeResolver : XmlUrlResolver,IDisposable {

                FileStream stream = null;

                public LocalDocumentTypeResolver(String systemEntry) {

                        stream = new FileStream(systemEntry,

                                FileMode.Open,

                                FileAccess.Read,

                                FileShare.Read);

                }

               

                override public object GetEntity(Uri absoluteUri, string role, Type ofObjectToReturn) {

                        return stream;

                }

 

                #region IDisposable Members

                // xsd kullanırken data source olarak result gösterilirse file used kalıyor

                // onun için LocalDocumentTypeResolver IDispose olmak zorunda

                public void Dispose() {

                        stream.Dispose();

                        stream = null;

                        GC.Collect();

                }

                #endregion

        }

        #endregion

 

         Artık yerel dosyalardan doğrulama bilgisini okuyabildiğimize göre XML verileni bu dosyalara göre doğrulayabiliriz.

/// <summary>

/// verilen mesaja ve tip tanımlama dosyasına gre veri kümesi üretir

/// </summary>

/// <param name="message">ayrıştırılacak mesaj</param>       

/// <param name="validateFilePath">veri kontrolünü sahlayacak danımlama dosyası tam yolu</param>

/// <param name="rootElement">mesajın root element</param>

/// <remarks>doğrulama yapılacak dosya uzantısı dtd veya xsd olmalıdır</remarks>

/// <exception cref="ArgumentOutOfRangeException">Doğrulama dosyası xsd veya dtd değil</exception>

/// <returns>tanımlama dosyasına göre oluşturulmuş veri kümesi</returns>

public static System.Data.DataSet Dispacth(string message, string validateFilePath, string rootElement) {

        if (string.IsNullOrEmpty(rootElement))

                throw new ArgumentException("rootElement",

                        "XML doğrulaması yapılacak xml root element verilmelidir.");

        if (!Regex.IsMatch(validateFilePath.ToLower(), @"(.)*\.dtd$|(.)*\.xsd$"))

                throw new ArgumentOutOfRangeException("validateFilePath",

                        "XML doğrulama dosyası 'dtd' veya 'xsd' uzantılı olmalıdır.");

 

        DataSet result = new DataSet();

 

        using (LocalDocumentTypeResolver fileResolver = new LocalDocumentTypeResolver(validateFilePath) ) {               

                XmlReaderSettings xmlSetting = new XmlReaderSettings();

                if (Regex.IsMatch(validateFilePath.ToLower(), @"(.)*\.dtd$")) {

                        if (message.IndexOf("<!DOCTYPE") == -1)

                                message = @"<?xml version='1.0'?><!DOCTYPE " +

                                        rootElement + " SYSTEM '" +

                                        validateFilePath + "'>" + message;

                        xmlSetting.ValidationType = ValidationType.DTD;

                } else if (Regex.IsMatch(validateFilePath, @"(.)*\.xsd$")) {

                        xmlSetting.Schemas.Add(null, XmlTextReader.Create(validateFilePath));

                        xmlSetting.ValidationType = ValidationType.Schema;

                }

                StringReader textReader = new StringReader(message);

                XmlTextReader xmlTextReader = new XmlTextReader(textReader);

                xmlTextReader.XmlResolver = fileResolver;

 

                xmlSetting.ValidationEventHandler += new ValidationEventHandler(xmlSetting_ValidationEventHandler);

                XmlReader xmlReader = XmlReader.Create(xmlTextReader, xmlSetting);

                isSuccess = true;

                result.ReadXml(xmlReader);

                if (!isSuccess)

                        result = null;

        }

       

        return result;

}

 

static void xmlSetting_ValidationEventHandler(object sender, ValidationEventArgs e) {

        isSuccess = false;

}

 

         Yukarıda ki kod ne yapıyor: message ile verilen XML verisini validateFilePath konumunda bulunan DTD veya XSD uzantılı dosyayı LocalDocumentTypeResolver sınıfı kullanarak doğruluyor. XmlReader sınıfına XSD için kullanılacak şema eklemek gerekmektedir. DTD için ise şema bilgisi xml verinin en başında tanımlanmalıdır.

Uygulama kodu ise oldukça basit.

private System.Data.DataTable Dispatch() {

        string xml = txtXML.Text;

        string shemaFile = optDTD.Checked ? DTDFile : XSDFile;

        string rootElement = txtSchema.Text.Substring(0, txtSchema.Text.IndexOf(Environment.NewLine))

                .Split(' ')[1];

        SaveSchemaFile(shemaFile);

        System.Data.DataSet result = Framework.Dispatcher.Dispacth(xml, shemaFile, rootElement);

        return result.Tables[0];

}

        

         Dispatch işleminde bize gereken bir diğer işlev ise Serializable DataRow nesnesidir. Yani önce test edilecek veriyi oluşturmak gerekmektedir. DataRow sınıfı varsayılan yapılandırıcıya sahip olmadı için hiçbir şekilde Serialize haline getirilemez. Çözüm DataRow nesnesini DataTable içine alıp serialize edilmektir.

/// <summary>

/// DataRow xml olrak serialize eder

/// </summary>

/// <param name="row"></param>

/// <returns></returns

public static string SerializeRow(DataRow row) {

    Type tableType = row.Table.GetType();

    DataTable table = (DataTable)Activator.CreateInstance(tableType);

    DataRow newRow = table.NewRow();

    newRow.ItemArray = row.ItemArray;

    table.Rows.Add(newRow);

    StringWriter writer = new StringWriter();

    table.WriteXml(writer);

    return writer.ToString().Replace("xml:space=\"preserve\"", "");

}

 

/// <summary>

/// xml string üzerinden DataRow üretir

/// </summary>

/// <param name="xmlDataSource">xml data source</param>

/// <param name="tableType">data table type</param>

/// <returns>data row</returns>

public static DataRow DeseriazeRow(string xmlDataSource, Type tableType) {

    StringReader reader = new StringReader(xmlDataSource);

    DataTable table = (DataTable)Activator.CreateInstance(tableType);

    table.ReadXml(reader);

    return table.Rows[0];

}

 

         Bir biri ile ayrı uzaylarda çalışan sistemler eğer web servisi gibi bir teknoloji kullanmadan haberleşiyorsa Dispatcher gibi bir çözüme gereksinim duyarlar. DTD ile temel XML doğrulama özellikle eski sistemler ile yapılan çalışmalarda çok fazla karşımıza çıkmaktadır.

Emre Coşkun

emrecoskun.net

11.05.07

 

 

 

 

Demo Uygulama