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

مشروع : تحويل نص بنية شجرية إلى تنسيق JSON

بدأه مصطفى 36a2 في 26 أكتوبر 2013 · 6 رد · 1,075 مشاهدة · في منتدى تطوير المواقع بـ PHP
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحمة الله وبركاته ..
إهداءً للأخ أحمد أبو السعود والأخ عبد اللطيف عرفانا لهما بالجميل ..فقد تعلمت php حقيقة من خلال دروسهما في دورة (لنبدأ مع PHP )
أقدّم هذا البرنامج ... كتابة خريطة على هيئة شجرة وتحويلها إلى ترميز JSON .

فكرة البرنامج :

نحتاج في كثير من التطبيقات إلى تشكيل شجرة من البيانات ..
مثلاً لنفترض أننا نصنّف الدول ..
هناك دول آسيوية ودول افريقية ..
والدول الآسيوية تحوي دول عربية ..
والدول العربية الآسيوية تحوي دول المتوسط ودول الخليج ودول البحر الأحمر ..

وهنا يمكننا الاعتماد على الترميز التالي (فكرته بسيطة جدا من تصميمي :P )
1- نبدأ بالجذر بكتابة اسم الجذر دون أي فراغ قبله..
2- اذا اردنا أن نتفرّع عن الفرع الحالي نضيف فراغا قبل كتابة اسم الفرع ..
3- اذا اردنا اغلاق الفرع الحالي والعودة الى جذره أو جذر جذره ..الخ .. فقط ننقص عدد الفراغات السابقة للاسم بحيث يتساوى مع عدد فراغات الفرع الذي نريد ان نكون فيه .


(ملاحظة : جميع الحقوق محفوظة :D )
لنبدأ بمثال بسيط :

مثال
 مثال برمجي
  لغات البرمجة
   C
   C++
   Php
   والمزيد
 مثال حقيقي
  مشرفو الفريق العربي
   أحمد
    أحمد سعود
    أحمد أبو عبد البر
   حسام
    حسام الشامي
   المزيد

يوضّح المثال السابق الآلية البسيطة جدا لتمثيل شجرة (بالفراغات السابقة للاسم )
وكما ترون يمكننا تمثيل الكثير من البنى بشكل شجرة كالفهارس مثلا ..

جاءت الفكرة عندما احتاج احدهم ان يكون الترميز السابق مفهوما من قبل لغات البرمجة ..
ووقع الاختيار على JSON بدون سبب :D

والآن إليكم الكود :
والذي يقوم بقراءة محتويات ملف ما .. مكتوبة بالصيغة المبتكرة السابقة .. ثم يحول البنية كاملة إلى تنسيق JSON ..
طبعا كالعادة الكود يحتاج التطوير والتنقيح والتحسين والتسريع الخ الخ ... ولكن لن أنتظر اكتماله ... فالكمال لله .. والتحسين على كواهلكم أيها الأخوة الأكارم :)
الكود مشروح سطرا سطرا ....(حسب الطريقة التي اتبعها أخي أحمد أبو السعود في أول مشاركة تعرفت عليه بها :) )

أرجو أن يكون فيه النفع والفائدة للجميع .. وارجو أن يكون فيه رد ولو بسيط لما قدّمه الأخوة أحمد أبو السعود والأخ عبد اللطيف في دورة الphp الرائعة :)

<!--
//ملاحظة حتى لا يحدث خلط بين العربي والأجنبي قد أكتب كلمات انكليزية بالعربي مثل جيسن أو بي اتش بي .. رغم أني أكره فعل ذلك
--!>
<?php//بداية الكود
$output="";//متحول الخرج : ويحتفظ بكل ما سنطبعه لا حقا
function Print_($a)//دالة الطباعة وتأخذ وسيطا النص المراد طباعته
{// بداية جسم الدالة
global $output;//الاشارة الى اننا سنستعمل متحول الخرج الموجود خارج الدالة
    echo $a;//طباعة النص على المتصفح
    $output.=$a;//وحفظ النص في المتحول
}//نهاية جسم الدالة
$Rhandler=fopen("1.txt",'r');//فتح الملف والقراءة منه وحفظ المقبض في متحول
$llevel=0;//متحول يحفظ عمق آخر فرع مررنا عليه
//كلمة عمق أعني بها مقدار التفرع داخل الشجرة
Print_("{");//طباعة بداية نص الجيسن
$x=false;//متحول يستعمل مرة واحدة لمنع كتابة الفاصلة في بداية الملف (أرجو التحسين ) وشكرا
for($i=0;//حلقة
!feof($Rhandler);//طالما لم نصل لنهاية المف الذي نقرأ
$i++,//ملاحظة : هذا المتحول ليس له أي عمل
$llevel=$clevel)//عند نهاية كل دورة نحفظ العمق الحالي في المتحول الدال على آخر عمق مررنا عليه
//l = last
//c = current
{//بدء الحلقة
    $content=fgets($Rhandler);//قراة سطر وحيد من الملف وحفظه في متحول
    for($clevel=0;$content[$clevel]==' ';$clevel++);//حلقة تعد الفراغات في بداية الاسم
    //عدد الفراغات هو نفسه عمق الفرع في الشجرة
    //الاسم يحتوي فراغات في بدايته ورموز نهاية السطر في نهايته لذلك سنقوم بازالتها
    $buffer="";//المتحول الذي سنحفظ فيه الاسم بعد التعديل
    for($i=$clevel;$i<strlen($content)&&$content[$i]!="\r"&&$content[$i]!="\n";$i++)
        $buffer.=$content[$i];//نأخذ حرفا حرفا من السطر حتى نصل الى نهايته دون أخذ محارف نهاية السطر
    $content=$buffer;//نعيد حفظ المحتوى في المتحول القديم
    //سنبدأ بخوارزمية التحول إلى جيسن
    if($clevel==$llevel)//في حال كان العمق الحالي هو نفس العمق السابق
    {//فهذا يعني أننا في نفس المصفوفة وعلينا اضافة عنصر فقط
    if($x)//محقق من اجل جميع العناصر عدا أول جذر أي عند بداء الملف فقط
        {
            Print_(":\"info\"");//نضع أي محتويات تخص العنصر حتى لا نتركه بدون محتوى فنحن في حاوية ترابطية تحفظ الاسم وتحفظ المحتوى معا
            Print_(",\"$content\"");//ثم نضع فاصلة ونطبع امحتوى السطر
        }
    else
        {
            Print_("\"$content\"");//نفس الكلام السابق ولكن بدون فاصلة البدء
            $x=true;//حتى لا ندخل الى هنا ثانية
        }
    }
    else if($clevel<$llevel)//حالة الخروج من الفرع الى مستوى سابق
    {
        Print_(":\"info\"");//نطبع اي محتوى لآخر فرع كنا فيه
        for($k=$clevel;$k<$llevel;$k++)
            Print_("}");//لقة تقوم بإغلاق الأقواس بنفس كمية الفرق بين المستويين
        Print_(",\"$content\"");//ثم نطبع محتوى السطر بعد الفاصلة بعد أن وصلنا الى المستوى المطلوب
    }
    else//حالة انشاء فرع جديد
    {
        Print_(":{\"$content\"");//نضع نقطتين للدلالة على وجود محتوى للفرع الحالي وأول عنصر فيه هو المحتوى الحالي
    }
}//عند الخروج من الحقة يكون الملف قد انتهى
Print_(":\"info\"");//نضع أي محتوى لآخر فرع كنا فيه
for($k=0;$k<$llevel;$k++)
    Print_("}");//ونغلق كل الاقواس المفتوحة
Print_("}");//ونغلق قوس البداية
fclose($Rhandler);//ونغلق الملف
//والآن للتأكد سنقوم بالتحويل والتحويل العكسي للتأكد أن التنسيق صحيح والمفترض طباعة كل ما تم طباعته ساقبا مرة أخرى بتطابق تام
echo "</BR>\n".json_encode(json_decode($output));
?>//نهاية الكود
//الحمد لله على فضله ونعمائه
//أخوكم مصطفى

(أرجو من الله ألا يتم استعمال البرنامج لأي غرض لا يرضيه بأي شكل . وأن يكون استخدامه لخير المسلمين في اي مكان ... وهو ولي التوفيق)

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

(ملاحظة : أرجو عدم كتابة ردود تحتوي على عبارات الشكر فقط ... فليس فيها نفع لمن سيقرأ المشاركة من بعدك  .. بل حاول الإفادة بملاحظة على الكود أو بتحسين أو تطوير أو اقتراح أو فكرة جديدة .. وجزاك الله خيرا )
 

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 27 أكتوبر 2013 في 00:48

2
#2

لمن أحب قراءة الكود بدون شرح فهذه هو :

<?php
$output="";
function Print_($a)
{
global $output;
    echo $a;
    $output.=$a;
}
$Rhandler=fopen("1.txt",'r');
$llevel=0;
Print_("{");
$x=false;
for($i=0;!feof($Rhandler);$i++,$llevel=$clevel)
{
    $content=fgets($Rhandler);
    for($clevel=0;$content[$clevel]==' ';$clevel++);
    
    $buffer="";
    for($i=$clevel;$i<strlen($content)&&$content[$i]!="\r"&&$content[$i]!="\n";$i++)
        $buffer.=$content[$i];
    $content=$buffer;
    
    if($clevel==$llevel)
    {
    if($x)
        {
            Print_(":\"info\"");
            Print_(",\"$content\"");
        }
    else
        {
            Print_("\"$content\"");
            $x=true;
        }
    }
    else if($clevel<$llevel)
    {
        Print_(":\"info\"");
        for($k=$clevel;$k<$llevel;$k++)
            Print_("}");
        Print_(",\"$content\"");
    }
    else
    {
        Print_(":{\"$content\"");
    }
}
Print_(":\"info\"");
for($k=0;$k<$llevel;$k++)
    Print_("}");
Print_("}");
fclose($Rhandler);

echo "</BR>\n".json_encode(json_decode($output));
?>

وهذا ملف صغير يحوي بنية شجرية لما يشبه القاموس ( للتجربة على الكود )

Dictionary
 A
  AA
   AARDVARK
  AB
   ABNORMAL
  AC
   ACCESSORIES
 B
  BA
   BAND
  BE
   BEEM
 C
  CA
   CARRIER
  CE
   CERTAIN
 Z
  ZE
   ZEBRA
  ZO
   ZORO
 MOSTAFA 36A2
  first and last THANKS GOD
  THEN
   THANKS TO AHMAD ABO ALSAOUD
   THANKS TO ABD ALLATIF
   THANK YOU :)

إذا لم يعمل الكود فالسبب الوحيد المعروف حاليا هو أنك تستعمل محارف غير مسموحة في json .. مثل الحروف العربية للأسف (يرجى قراءة رد الأخ أحمد أدناه )

لا تنسونا من صالح دعائكم :)

تم تعديل هذه المشاركة بواسطة مصطفى 36a2 في 27 أكتوبر 2013 في 19:04

2
#3

شكراً لك على هذه الكلمات الطيبة , بارك الله لك في علمك وأثابك الفردوس ., أنت من تستحق كل هذا الثناء لما تقدمة هنا من موضوعات متميزة .

 

الحقيقة فكرة جميلة جداً , فكرتني بإسلوب لغة بايثون الجميل في الكتابة .

 

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

 

اقتباس
إذا لم يعمل الكود فالسبب الوحيد المعروف حاليا هو أنك تستعمل محارف غير مسموحة في json .. مثل الحروف العربية للأسف :(

- يدعم تنسيق json اللغة العربية وأي لغة أخرى حيث أنه يعتمد على الترميز UTF-8 في ترميز الحروف ويتوافق مع نظام ASCII , إذاً عليك تحويل الحروف للنظام السادس عشر على الشكل \x0000 داخل تنسيق json , إستخدم دالة json_encode لطباعة بيانات باللغة العربية وأحفظ الناتج في ملف وشاهد ثم إفحه لترى كيفية الترميز .

تم تعديل هذه المشاركة بواسطة ahmedsaoud31 في 27 أكتوبر 2013 في 12:04

1

لاتحسبن العلم ينفع وحده مالم يتوج ربه بخلاق

لا إله إلا أنت سبحانك إني كنت من الظالمين

#4

هل جربت YAML؟

(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

#5

هل السؤال لي ؟ لا , بماذا أستعمله ؟

وشكرا لك :)

#6

صيغة لتمثيل البيانات بطريقة مشابهة http://yaml.org/
 

(map share people)

فضلا لاتقم بمراسلتي من أجل أسئلة لها أقسامها في المنتدى حتى تعم الفائدة على الجميع وللحصول على إجابات أفضل من أعضاء أكثر خبرة.
Weblog
@bitbucket
@xmonader

#7

أي طريقة مشابهة يا رجل :) مشروع ضخم جداً هذا الـ YAML .. وتدعمه الكثير من اللغات كما يبدو .. وله عدة طرق تمثيل لكل أنواع البيانات ...

اما مشيريعي الصغير فهو أداة منمنمة للتعامل مع الأشجار :)

شكرا لك ..يبدو أن طرق تمثيل البيانات الموجودة في الساحة لا يمكن إحصاؤها !!

 

بالتوفيق

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