الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

افكار وتلميحات حول الفئة XmlTextWriter

مغلق
بدأه Dr.Pain في 24 سبتمبر 2005 · 4 رد · 762 مشاهدة · في Microsoft Visual Basic.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته ..............

تتلخص عملية كتابة بيانات XML بواسطة الفئة XmlTextWriter بالخطوات التالية :

1 - تعريف متغير من نوع الفئة XmlTextWriter مع تمرير مسار واسم الملف الذي سوف تقوم الفئة بانشائه وكذا تمرير ترميز المحارف Encoding .

2 - كتابة البيانات بواسطة طرق هذه الفئة .

3 - اغلاق المجرى المرتبط بالملف المنشئ بواسطة الطريقة Close .

الان انظر الى مستند XML التالي :

<?xml version="1.0"?>

<!-- am comment -->

<Root>

<Element No="1">am string</Element>

<!--

<Element No="2">am string</Element>

<Element No="3">am string</Element>

<Element No="4">am string</Element>

-->

</Root>

نلاحظ ان هذا المستند يتكون من العناصر التاليه :

ال Tag الذي يدل على رقم اصدار ملف ال XML الحالي .

تعليق يحتوي على العبارة Am comment .

العنصر المسمى Root والذي يمثل العقدة الجذر للمستند .

العنصر ُElement والذي يحتوي على الخاصية ( attribute ) المسماة No والقيمة النصية am String .

الان من اجل كتابة المستند السابق وجب علينا معرفة الطرق التي توفرها الفئة XmlTextWriter لكتابة كل عنصر من العناصر السابقة الذكر .

والطرق هي كالاتي :

من اجل كتابة ال Tag الذي يدل على رقم اصدار ملف ال XML الحالي نستخدم الطريقة :

WriteStartDocument()

من اجل كتابة التعليقات في المستند نستخدم الطريقة :

WriteComment

من اجل كتابة عنصر ما نستخدم الطريقه :

WriteStartElement

من اجل كتابة خاصية ( attribute ) لعنصر ما فاننا نستخدم الطريقه :

WriteAttributeString

وذلك بتمرير كلا من اسم الخاصية وقيمتها .

من اجل كتابة قيمة للعنصر فاننا نستخدم الطريقة :

WriteString

وذلك بتمرير القيمة النصية المراد كتابتها .

الان انظر الى الشكل التالي :

23_09_05_01_26_24_1127507184close_Elements.JPG

من الشكل السابق نلاحظ ان العنصر Root يقع في المستوى الاول بالنسبة للمستند ككل , وان العنصر Element

يقع في المستوى الاول بالنسبة للعنصر Root لذا وجب علينا اغلاقة ان اردنا الكتابة في المستوى الاول بالنسبة

للعنصر Root والا فان الكتابة سوف تتم داخل العنصر ُElement .

من اجل اغلاق المستويات فاننا نستخدم الطريقة :

WriteEndElement()

ملاحظـــــــــــــــــــــة

-------------------------- كل الملفات سوف تنشى في المجلد Bin للمشروع الذي تعمل عليه .

الان سوف نقوم بكتابة المستند الذي تم نقاشه من سابق :

 Dim MyXml As New Xml.XmlTextWriter(IO.Directory.GetCurrentDirectory & "\TestXml.xml", System.Text.Encoding.Unicode)

/// تعريف متغير من نوع الفئة XmlTextWriter مع تمرير كلا من مسار واسم الملف الذي ستقوم هذه الفئة بانشائه وكذا

ترميز المحارف Encoding :

Dim i As Integer

        MyXml.WriteStartDocument

()

//// الطريقة التي تحدد اصدار ملف XML الحالي

     MyXml.WriteComment("am comment")

///// كتابة تعليق

     MyXml.WriteStartElement("Root")

///// كتابة العقدة الجذر Root

For i = 1 To 4
            MyXml.WriteStartElement("Element")

///// كتابة العقدة Element

 MyXml.WriteAttributeString("No", i.ToString)

///// كتابة الخاصية No مع اعطائها قيمة المتغير I

   MyXml.WriteString("am string")

///// كتابة القيمة النصية التي سوف يحتويها العنصر Element

     MyXml.WriteEndElement()

///// اغلاق العنصر Element وذلك حتى نتمكن من كتابة عنصر Element اخر في نفس مستوى العنصر Element

السابق - جرب ان لاتقوم باستخدام الطريقة WriteEndElement !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  Next
        
        MyXml.WriteEndElement()

//////// اغلاق العنصر الجذر Root

 MyXml.Close()

///////// اغلاق المجرى المرتبط مع الملف

الان دعنا ناخذ مثالا اخر ...........

هناك لعبة مشهورة الا وهي لعبة كتابة الارقام و هي تتمثل في ان اعطيك رقما ومن ثم انت عليك ان تقوم بكتابة

الارقام من واحد الى ذلك الرقم حيث اننا نكتب الرقم مع الاعداد التي تسبقه فاذا فرضنا انه لدينا الرقم 5 فان حل

اللعبة سيكون كالاتي :

الحل

--------

1

2 يسبقه العدد 1

3 يسبقه العدد 2 و العدد 1

4 يسبقه العدد 3 و العدد 2 و العدد 1

5 يسبقه العدد 4 العدد 3 و العدد 2 و العدد 1

حسنا اذا قلت لك خذ الرقم 5 ولكنني اريد النتيجة على شكل ملف XML , فان الذي سوف تفعله سيكون مشابها

للاتي :

 Dim i, j As Integer

        Dim MyXml As New Xml.XmlTextWriter("c:\WhoB4Me.xml", System.Text.Encoding.Unicode)

        MyXml.WriteStartDocument()

        MyXml.WriteStartElement("Root")


        For i = 1 To 5

            MyXml.WriteStartElement("ElementNo_" & i.ToString)

//////// كتابة الرقم ودعنا نتفترض اننا قد كتبنا العددين 1 و 2 واننا نقوم بكتابة العدد 3

For j = i - 1 To 1 Step -1

                MyXml.WriteStartElement("Am_B4_U")

////// كتابة الارقام التي تسبق المتغير I ان وجدت فان كان المتغير I يساوي 3 مثلا فانه عن طريق هذه الحلقة

سوف يتم كتابة عنصرين حيث يحتوي الاول على القيمة 1 والثاني على القيمة 2 وذلك باستخدام الطريقة WriteString

مع تمرير قيمة المتغير J لها انظر السطر التالي :

                MyXml.WriteString(j.ToString)

///// كتابة قيمة المتغير J

      MyXml.WriteEndElement()

/////// اغلاق العدد السابق من اجل كتابة عدد جديد ان وجد على مستوى العقدة التي تحتوي على القيمة 3

           Next

            MyXml.WriteEndElement()

////////// اغلاق العقدة التي تحتوي على القيمة 3حتى نتمكن من كتابة عقدة جديدة تحتوي على الرقم 4 وهكذا .

 Next

        MyXml.WriteEndElement()

/////// اغلاق العنصر الجذر Root

 MyXml.Close()

///////// اغلاق المجرى المرتبط مع الملف

الان دعنا نستفيد من هذه الفئة بشكل عملي :

اذا افترضنا انه لدينا قاعدة بيانات اسمها Students Registeration وبها جدول اسمه Students حيث يحتوي هذا الجدول

على حقلين هما :

StudentNo

StudentName

كل ما سنقوم به الان هو سحب البيانات الموجودة داخل هذا الجدول الى داخل DataReader ومن ثم سنقوم باخذ

البيانات الموجودة في ال DataReader ومن ثم كتابتها الى ملف XML يقوم بوصف البيانات الموجودة داخل الجدول

Students .

اي اننا نريد مستند على هذه الهيئة :

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

<Students_Registeration_DataBase>

<Tables>

<Student>

<Row>

<StudentNo>1</StudentNo>

<StudentName>Dr.Pain</StudentName>

</Row>

<Row>

<StudentNo>2</StudentNo>

<StudentName>gasan</StudentName>

</Row>

</Student>

</Tables>

</Students_Registeration_DataBase>

وهذا يعني انه لدينا قاعدة بيانات اسمها Students Registeration تحتوي على الجدول Students وبهذا الجدول

اثنان من الصفوف .

لكن قبل ذلك دعني اعرفك على بعض خصائص وطرق ال DataReader :

الخاصية FieldCount :

------------------------

تقوم هذه الخاصية بارجاع عدد الاعمدة الموجودة في الصف ( Row ) , وفي حالتنا هذه سوف تقوم بارجاع العدد 2

الخاصية Item :

-------------------

تقوم بارجاع قيمة العمود المحدد اي اننا لو قمنا بشئ مماثل للاتي :

Msgbox (dr.Item(0)) 
Msgbox (dr.Item(1))

وكان الحقل StudentNo يساوي 1 والحقل StudentName يساوي Dr.Pain فانها سوف ترجع :

1 و Dr.pain

او اذا قمنا بعمل التالي فاننا سوف نحصل على نفس النتيجة :

Msgbox (dr.Item("StudentNo")) 
Msgbox (dr.Item("StudentName"))

الطريقة GetName :

-----------------------

تقوم بارجاع اسم العمود المحدد اي اننا لو قمنا بشئ مماثل للاتي :

Msgbox (dr.GetName(0)) 
Msgbox (dr.GetName(1))

فاننا سوف نحصل على :

StudentNo

StudentName

اي اسماء الاعمدة وليست قيمها .

الطريقة Read :

-----------------

تقوم بارجاع القيمة True طالما ان هناك صفوف للقراءة والعكس .

حسنا الان دعنا نصيغ الموضوع برمجيا :

      Dim Cnn As New OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & IO.Directory.GetCurrentDirectory & "\Students Registeration.mdb")

//////// تعريف كائن اتصال من النوع OleDbConnection

   Dim Com As New OleDb.OleDbCommand("Select * from students", Cnn)

////////// تعريف كائن امر من النوع OleDbCommand

       Dim dr As OleDb.OleDbDataReader

//////// تعريف كائن من النوع OleDbDataReader

       Cnn.Open()

//////// فتح كائن الاتصال

       dr = Com.ExecuteReader

تعبئة الكائن dr بالصفوف بواسطة الطريقة ExecuteReader والتي تعيد فئة من نوع OleDbDataReader

والتي ينفذها الكائن OleDbCommand

       Dim Writer As New Xml.XmlTextWriter(IO.Directory.GetCurrentDirectory & "\Students Table info.xml", System.Text.Encoding.Unicode)

///////// تعريف كائن من الفئة XmlTextWriter

      Writer.WriteStartDocument()

//// الطريقة التي تحدد اصدار ملف XML الحالي

      Writer.WriteStartElement("Students_Registeration_DataBase")

/////// انشاء العقدة الجذر للمستند و المسماة Students_Registeration_DataBase

        Writer.WriteStartElement("Tables")

/////// انشاء العقدة المسماة جداول

    Writer.WriteStartElement("Student")

/////// انشاء العقدة التي تدل على ان هذه هي البيانات الخاصة بالجدول Student

    Dim i As Integer

        While dr.Read

////////////// تنفيذ الطريقة Read والتي تعود بالقيمة True طالما ان هناك صفوف للقراءة

           Writer.WriteStartElement("Row")

/////////// انشاء عقدة صف جديد

        For i = 0 To dr.FieldCount - 1

الدوران على بمقدار يساوي عدد الاعمدة الموجودة في الصف وذلك باستخدام الخاصية FieldCount

               Writer.WriteStartElement(dr.GetName(i))

//////// انشاء عقدة جديدة تحتوي على اسم العمود وذلك باستخدام الطريقة GetName والتي تعود باسم العمود

               Writer.WriteString(dr.Item(i))

//////// كتابة قيمة العمود وذلك باستخدام الخاصية Item والتي تعود بقيمة العمود

               Writer.WriteEndElement()

////////// اغلاق العقدة التي تحتوي على اسم العمود

          Next

            Writer.WriteEndElement()

////////// اغلاق العقدة المسماة Row اي اغلاق العقدة التي تشير الى صف ما والبدء بكتابة صف جديد

       End While

        Writer.WriteEndElement()

////////// اغلاق العقدة Students

       Writer.WriteEndElement()

////////// اغلاق العقدة Tables

       Writer.WriteEndElement()

/////// اغلاق العقدة Students_Registeration_DataBase

       Writer.Close()

/////// اغلاق مجرى الملف

       Cnn.Close()

///////// اغلاق كائن الاتصال

الكلام السابق قد يراه البعض جميلا لكن دعني اسالك الان ماذا لو اردنا كتابة بيانات موجودة في DataReader اخرى

اعتقد ان الاجابة ستكون اننا سوف نقوم بكتابة الكود السابق مرة اخرى مع بعض التعديلات في الاسماء !!!!!!!!!

لذلك لماذا لا نستفيد من تقنية الوراثة ونقوم بعمل فئة ترث الفئة XmlTextWriter ومن ثم نقوم بتضمين طريقة

اسمها WriteDataReader , حيث اننا سوف نقوم بتمرير فئة من نوع DataReader للطريقة ومن ثم سوف تتولى هي

مهمة كتابة البيانات الموجودة في ال DataReader .

اذن دعنا نقوم بعمل فئة اسمها MyXmlTextWriter ومن ثم دعها ترث من الفئة XmlTextWriter .

لكن لا تنسى بعد الوراثة ان تقوم بتنفيذ طريقة البناء الخاصة بالفئة الجديدة MyXmlTextWriter .

    Class MyXmlTextWriter
        Inherits Xml.XmlTextWriter

        Sub New(ByVal filename As String, ByVal encoding As System.Text.Encoding)
            MyBase.New(filename, encoding)
        End Sub

الان قم ببناء الطريقة التي اسمها WriteDataReader :

Sub WriteDataReader(ByVal dr As OleDbDataReader)

            Dim i As Integer

            While dr.Read

                WriteStartElement("Row")

                For i = 0 To dr.FieldCount - 1

                    WriteStartElement(dr.GetName(i))
                    WriteString(dr.Item(i))
                    WriteEndElement()


                Next

                WriteEndElement()

            End While
        End Sub

لاحظ ان الكود السابق لم يتغير عن الكود المكتوب قبل الوراثة لكتابة بيانات ال DataReader لذا لا داعي للتعليق

عليه .

الان ما عليك الا ان تقوم باستدعاء الطريقة WriteDataReader مع تمرير فئة من نوع DataReader .

 Writer.WriteDataReader(dr)

الان افتح المستند Students Table info_After والموجود في المجلد Bin الخاص بالمشروح .

ماذ تلاحظ ؟؟؟؟؟ الملاحظ ان الصفوف فصلت بواسطة الكلمة Row حسنا ان لم تعجبك هذه الكلمة واردت ان

تعطي لمستجدم الفئة حرية اكبر في اختيار الاسم الذي سوف يتم فصل الصفوف به ما عليك الا ان تقوم باعادة

تحميل الطريقة WriteDataReader مع جعل الطريقة المحمله تستقبل وسيطا نصيا الى جانب وسيط الفئة DateReader

Overloads Sub WriteDataReader(ByVal dr As OleDbDataReader, ByVal SplitterName As String)

            Dim i As Integer

            While dr.Read

                WriteStartElement(SplitterName)

                For i = 0 To dr.FieldCount - 1

                    WriteStartElement(dr.GetName(i))
                    WriteString(dr.Item(i))
                    WriteEndElement()

                Next

                WriteEndElement()

            End While
        End Sub

الان بقى لي تعليق اخير على الطريقة WriteDataReader نلاحظ ان الوسيط الاول عبارة عن فئة من النوع OleDbDataReader

الان دعني اسالك سؤالا كم انواع DataReader لدينا ؟؟؟؟؟؟؟؟؟؟؟

لدينا خمسة انواع وهي :

OdbcDataReader

OleDbDataReader

OracleDataReader

SqlCeDataReader

SqlDataReader

لاحظ واحدة من اجل قاعدة بيانات اكسيس والثانية لي SqlServer وواحدة لي Oracle ..... الخ .

اذن اذا كانت معي DataReader من نوع SqlDataReader والخاصة بي SqlServer فانه للاسف لن تعمل معي الطريقة

WriteDataReader بنجاح لان نوع الوسيط كان من نوع OleDbDataReader !! اذن ما العمل ؟؟؟؟؟؟؟

قد يقول احد ما الحل هو في اعادة تحميل الطريقة WriteDataReader خمس مرات مع تغيير نوع الوسيط في كل مرة :

 Overloads Sub WriteDataReader(ByVal dr As OdbcDataReader)

 End Sub

 Overloads Sub WriteDataReader(ByVal dr As OleDbDataReader )

 End Sub

 Overloads Sub WriteDataReader(ByVal dr As OracleDataReader)

 End Sub

 Overloads Sub WriteDataReader(ByVal dr As SqlCeDataReader)

 End Sub

 Overloads Sub WriteDataReader(ByVal dr As SqlDataReader )

 End Sub

ومن ثم اعادة تحميل الطرق التي تحتويعلى اسم فاصل الصفوف :

Overloads Sub WriteDataReader(ByVal dr As OdbcDataReader, ByVal SplitterName As String)

 End Sub

 Overloads Sub WriteDataReader(ByVal dr As OleDbDataReader , ByVal SplitterName As String)

 End Sub

 Overloads Sub WriteDataReader(ByVal dr As OracleDataReader , ByVal SplitterName As String)

 End Sub

 Overloads Sub WriteDataReader(ByVal dr As SqlCeDataReader , ByVal SplitterName As String)

 End Sub

 Overloads Sub WriteDataReader(ByVal dr As SqlDataReader , ByVal SplitterName As String)

 End Sub

اذن لاحظ معي اننا قمنا بتكرار العمل السابق لعشر مرات وهذا قد يبدوا مقبولا لكن دعني اسالك سؤالا جديدا

اذا افترضنا ان هناك 100 DataReader جديدة ظهرت في السوق فهل ستقوم باعادة تحميل الطرق ؟؟؟؟؟ ام ماذا ؟؟

اذا كان الجواب نعم فلاحظ انك سوف تقوم باعادة تحميل الطريقة WriteDataReader لي 200 مرة .

ولكن ان كنت ذكيا فانك سوف تقول لي لا لن اقوم باعادة تحميل الطرق !!!!!!!! بل ساقوم باستخدام الواجهات حيث

انني سوف اقوم بتحميل الطريقة لمرتين فقط ولكنني لن امرر وسيطا من النوع OleDbDataReader او من النوع

SqlDataReader او كائن من كان من انواع ال DataReader بل ساقوم بتمرير واجهة !!!!! نعم واجهة وهذه الواجهة هي

IDataReader والتي تنفذها كل ال DataReader بدون استثناء :

Overloads Sub WriteDataReader(ByVal dr As IDataReader)

code ...........

        End Sub

Overloads Sub WriteDataReader(ByVal dr As IDataReader, ByVal SplitterName As String)

code ...........           

        End Sub

من خلال هذه الواجهة تضمن الطريقة WriteDataReader ان كل الفئات التي سوف تمرر لها تفوم بتنفيذ اعضاء الواجهة

IDataReader .

ان لم تقتنع بفكرة تمرير الواجهة IDataReader اقول لك دعني انا وانت نستعرض اعضاء الواجهة IDataReader :

23_09_05_01_53_12_1127508792IDataReader_Members.JPG

من الاعضاء السابقيين نلاحظ ان الطريقة Read هي عضو من اعضاء الواجهة IDataReader .

تقول لي الان ماذا عن بقية الخصائص والطرق والتي هي :

FieldCount

GetName

Item

ستقول لي انها ليست اعضاء في الواجهة IDataReader !!!! لذا اقول لك انظر الى الشكل التالي :

23_09_05_01_57_13_1127509033inherits_IDataRecord.JPG

نلاحظ من الشكل السابق ان الواجهة IDataReader ترث اعضاء الواجهة IDataRecord وايضا يرينا الشكل السابق

الفئات التي تقوم بتنفيذ الواجهة IDataReader .

الان انظر الى الشكل التالي :

23_09_05_01_58_18_1127509098IDataRecord_Members.JPG

من الشكل السابق نلاحظ ان كل من :

FieldCount

GetName

Item

اعضاء في الفئة IDataRecord وبالتالي تلقائيا يصبحون اعضاء في الواجهة IDataReader لانها ترث من الواجهة IDataRecord

وبما ان :

FieldCount

GetName

Item

Read

اعضاء في الواجهة IDataReader وبما ان الفئات :

OdbcDataReader

OleDbDataReader

OracleDataReader

SqlCeDataReader

SqlDataReader

تقوم بتنفيذ الواجهة IDataReader اذن بالتالي كل فئة من الفئات السابقة سوف تحتوي على الطرق والخصائص الموجودة

في الواجهة IDataReader ومن ضمنها :

FieldCount

GetName

Item

Read

اذن لن تهتم الطريقة WriteDataReader بنوع الوسيط الممرر بعد الان شريطة ان ينفذ الواجهة IDataReader .

والسلام عليكم ورحمة الله وبركاته ........................................................................

اخوكم Dr.Pain

#2

أخي Dr.Pain

أعتذر عن عدم الرد في درسك الاول XmlTextReader لأني كنت مشغول ولم أرى ردك إلا الآن

أما بالنسبة لدرس اليوم ماشاء الله إبداع وأنا مازلت لم أتم قرائته

لكن كان طلبي السابق مختلف (للأسف لم أحسن صيغة السؤال )

سؤالي حله أعتقد بسيط جدا ولا يحتاج لمعرفة في كتابة xml يدويا أبدا ،،،

أنا افترضت أن هناك مثلا برنامج ما يتعامل مع قواعد بيانات sqlserver

هذا البرنامج يحتوى على DataSet يتم تعبئتها بواسطة DataAdapter ثم

تسند كمصر بيانات للـ DataGrid1 الموجودة على الفورم

الآن يقوم المستخدم بالتعديل على البيانات من خلال الDataGrid1 ثم يضغط على زر

حفظ لحفظ التعديلات

هنا السؤال:

لو كانت قاعدة البيانات موجودة على السيرفر ..

وفجأة حصل خلل في الشبكة

هناك طريقة لتجاوز المشكلة بدون إعاقة البرنامج عن العمل

وهي استخدام xml بحيث هناك أمر موجود جاهز من ضمن خصائص datagrid

ألا وهو writexml تقريبا حسب ما أذكر لعدم توفر اللغة عندي حاليا

( بسبب عطل جهازي وسيحتاج إسبوع لتصليحه)

المهم بواسطة هذا الأمر يمكنك التخزين على الجهاز نفسه في ملف أنت تحدده وعندما تعود الشبكة للعمل يتم

قراءة البيانات المخزنة محليا في صيغة xml في الملف المحدد باستخدام أيضا أمر آخر readxml

وإرسالها للسيرفر

وكمثال آخر

نفترض أن شركة عندها مندوب

ويحتاج أن يكون معه في تنقلاته بين العملاء "نوت بوك" وعليه برنامج الشركة

والذي قد يضيف عليه بيانات جديدة

هنا بإمكاننا أن نصمم البرنامج بحيث يخزن البيانات الجديدة التي يحدثها أو يضيفها المندوب

(كالفواتير الجديدة مثلا أو بيانات العملاء الجديدة)

أن يخزنها على الجهاز بصيغة xml وعند عودته للشركة يتم إرسال البيانات الجديدة لقاعدة البيانات الموجودة على السيرفر

أتمنى أن يكون قد وضح الطلب

والسلام عليكم ورحمة الله

أخوك أبو حسين

فلسطين الزاهية بألوان الحب والسلام

ذلك الطعم الزيتوني الذي يتدفق عسلاً من أفواه بساتينها وحدائقها

تشتاق إليها نفوس المتقين وترنوا للسجود فيها جباه المسلمين

#3

السلام عليكم ورحمة الله وبركاته ...........

رمضان كريم مؤخرا ..... وعيدكم مبارك مقدما :)

اخي seahmad ارجوا ان يفيدك هذا :rolleyes: واسف على التاخير :( الدنيا اخذتنا بعيد :unsure:

اخوك Dr.Pain

HowToFillDataSetfromXmlFile.zip

#4

جزاك الله كل خير شرح رائع ورمضان كريم وكل عام وانت بخير

VB.NET and C# Comparison

http://www.harding.edu/fmccown/vbnet_csharp_comparison.html

002.gif

=-=-=-=-=-=-=
ذو العلم يشقى فى النعيم بعلمه .:. واخو الجهالة فى الشقاوة ينعم
=-=-=-=-=-=-=
يا من بدنياه اشتغل . قد غره طول الأمل . فالموت يأتى بغتة . والقبر صندوق العمل
=-=-=-=-=-=-=
ان لم تستطع ان تجد ما تفعله فافعل ما لم تسطع ان تجده

screen_shot_2011-05-19_at_12.44.49_pm.pn

هذا الموضوع مغلق.

مواضيع مشابهة