لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 11/06/22 في كل الموقع
-
اذا كنت اقوم ببناء موقع الكتروني وتطبيق لنفس الموقع هل الnode js هي افضل داتا بيز لربط قواعد بيانات هذا المشروع ؟2 نقاط
-
يظهر خطأ عند التنفيذ raise ImproperlyConfigured( django.core.exceptions.ImproperlyConfigured: Could not find the GDAL library (tried "gdal304", "gdal303", "gdal302", "gdal301", "gdal300", "gdal204", "gdal203", "gdal202"). Is GDAL installed? If it is, try setting GDAL_LIBRARY_PATH in your settings. علما ان Setting.py: from pathlib import Path import os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY ='django-insecure-0izl^kd59le=r$_eke-7yv#hed&i&20)$#####' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'patient', 'accounts', 'import_export', 'index', 'blog', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ] MIDDLEWARE = [ 'django.middleware.csrf.CsrfViewMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'Medical.urls' CRISPY_TEMPLATE_PACK ='bootstrap4' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': ['templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'Medical.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME':'Medical', 'USER': 'postgres', 'PASSWORD':'123456', 'HOST': 'localhost', 'PORT': '5432', } } AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/4.1/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.1/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [ BASE_DIR / "static", ] MEDIA_URL = '/media/' MEDIAFILES_DIRS = [ BASE_DIR / "media", ] LOGIN_URL='accounts:login' # Default primary key field type # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # if not os.path.join(LOG_PATH): # os.mkdir(LOG_PATH) # MIDDLEWARE_CLASSES=( # 'easy_timezones.middleware.EasyTimezoneMiddleware', # ) DEFAULT_FROM_EMAIL = "will@wsvincent.com" EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend"1 نقطة
-
مثلا ، نأخذ هذا السكريبت def catch(): ... try: ... asd() ... except Exception as e: ... print e.message, e.args ... >>> catch() global name 'asd' is not defined ("الاسم asd غير معرف",) لكنه لا يمسك BaseException أو استثناءات الخروج من النظام SystemExit و KeyboardInterrupt و GeneratorExit: >>> def catch(): ... try: ... raise BaseException() ... except Exception as e: ... print e.message, e.args ... >>> catch() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 3, in catch BaseException >>> def catch(): ... try: ... raise BaseException() ... except: ... pass ... >>> catch() >>> تنبع جميع الاستثناءات من BaseException ، وتلك التي من المفترض أن تلتقطها يومًا بعد يوم (تلك التي سيتم طرحها للمبرمج) ترث أيضًا من Exception.1 نقطة
-
قمت بتنقيذ الخطوات جميعها لكن المشكلة مازالت موجودة1 نقطة
-
اولا يجب عليك معرفة ماهو الباك وماعمله لكي تعرف ان كان يفيدك او لا الباك لينك Backlink هو تقنية هدفها الترويج والإعلان عن ما يقدمه موقع الويب أو المتجر الإلكتروني الخاص بك. والمقصد منها بشكل بسيط، هي أي روابط موجودة على مواقع ويب أخرى بخلاف موقعك وتشير هذه الروابط إلى موقعك أو متجرك الإلكتروني. وتعود هذه الروابط أو الباك لينكس على متجرك الإلكتروني او موقعك بأهمية وفوائد عديدة من أهمها أنها تزيد من فرص ظهور موقعك في محركات البحث مثل جوجل. وهذا نظرًا لما تشير له هذه الروابط الخارجية، فهي تدل على مدى شعبية وانتشار موقع الويب أو المتجر الإلكتروني الخاص بك عبر شبكة الإنترنت. والآن بعد ما تعرفنا على ما هو باك لينك والمقصد منه بشكل بسيط، دعنا نتعرف على أهميته لموقع الويب أو المتجر الإلكتروني الخاص بك: أولًا: ترتيب موقعك في صفحات النتائج الأولى مع كثرة عدد الباك لينكات التي تقوم بإنشائها من أجل موقع الويب أو المتجر الإلكتروني الخاص بك، سترى محركات البحث أن متجرك ذات ثقة كبيرة. نظرًا لأنه يُسجل عدد كبير من الزيارات، مما يترتب عليه زيادة فرص ظهوره وترتيبه بشكل متقدم في نتائج محركات البحث. ثانيًا: زيادة حركة المرور على موقعك تعمل روابط الباك لينك على توجيه المستخدمين نحو صفحات هامة بموقفعك او مدونتك ، لذا تساهم في زيادة عدد زيارات موقعك وارتفاع معدل حركة المرور بشكل ملحوظ ثالثًا: زيادة قوة نطاق الموقع / الدومين أو Domain Authority سلطة الدومين يتم قياسها وفقًا لبعض المعايير والتي من أهمها عدد الباك لينكات أو الروابط الخلفية لموقعك او مدونتك. وخاصة في حالة وجودها في مواقع بالفعل تتمتع بدومين أثورتي عالي. ويساهم في ارتفاع الدومين الأثورتي الخاص بموقعك او بمدونتك أيضًا، عدد الزيارات التي يسجلها الموقع او المدونة والتي تنتج من الروابط الخلفية التي قمت بإنشائها.1 نقطة
-
ما هو action design pattern laravel وال repository design pattern وما الفرق بينهم وشكرا1 نقطة
-
صلاحيات المسؤول مطلوبة لتنفيذ هذه الأوامر. للقيام بذلك ، قم بتشغيل موجه الأوامر cmd كمسؤول (administrator) وأدخل الأوامر أعلاه. تحتاج إلى تسجيل الخروج وتسجيل الدخول مرة أخرى حتى تدخل الإعدادات حيز التنفيذ.1 نقطة
-
لقد وجدت ما يلي يعمل مع windows: قم بتشغيل python للتحقق مما إذا كانت python 32 أو 64 بت. قم بتثبيت OSGeo4W التالي (32 أو 64 بت) في C: \ OSGeo4W أو C: \ OSGeo4W64: ملاحظة: حدد تثبيت Express Web-GIS وانقر فوق التالي. في قائمة ‘Select Packages’ ، تأكد من تحديد GDAL ؛ يتم أيضًا تمكين MapServer و Apache افتراضيًا ، وقد يتم إلغاء تحديدهما بأمان. تأكد من تضمين ما يلي في settings.py: import os if os.name == 'nt': import platform OSGEO4W = r"C:\OSGeo4W" if '64' in platform.architecture()[0]: OSGEO4W += "64" assert os.path.isdir(OSGEO4W), "Directory does not exist: " + OSGEO4W os.environ['OSGEO4W_ROOT'] = OSGEO4W os.environ['GDAL_DATA'] = OSGEO4W + r"\share\gdal" os.environ['PROJ_LIB'] = OSGEO4W + r"\share\proj" os.environ['PATH'] = OSGEO4W + r"\bin;" + os.environ['PATH']1 نقطة
-
السلام عليكم،، لقعد حاولتُ إستخدام عدة تطبيقات لرسم المخططات التدفقية مثل (Mind Master, Lucidchart, mindomo, Word أيضاً🙃) لكن لم يتوفر في بعض منها الأشكال الازمة للمخططات الخاصة بالبرمجة، أو أنها مدفوعة إضافة إلى أن بعضها صعبة الاستخدام ومعقده. وأنا بحاجة لتطبيق -لإنشاء المخططات التدفقية- يكون: متوافق مع نظام MacOS. سهل الإستخدام (إن أمكن). يكون مجاني بالكامل، أو بنسخهمحدوده توفر المهام الازمة لعملي. أرجو مشاركتي إسم أو رابط للتطبيق/ات الذي تراه مناسب. خالص الشكر،،،1 نقطة
-
أفضل استعمال مواقع التعديل على استعمال تطبيق محدد، و ذلك ﻷنه يمكنك فتح هذه المواقع و العمل من أي جهاز سواء لابتوب أو هاتف محمول، كما أنها غالباً أسرع و أسهل في الاستعمال. شخصياً أقوم باستعمال diagrams حيث أنه يوفر كافة الخيارات التي أحتاجها و يوفر تصدير المخطط بصيغ متعددة بالإضافة إلى الكثير من الميزات الأخرى، و هو سهل الاستعمال.1 نقطة
-
لا يوجد بشكل عام شيء أفضل من شيء في عالم البرمجة و تطوير التطبيقات، لو وجد ذلك لما كان لدينا العديد من الخيارات. إن لكل قاعدة بيانات ميزات و مساوئ و عليك الإطلاع عليها و أنت فقط من يستطيع اتخاذ القرار حول أي واحدة ستقوم باستعمالها، و ذلك ﻷنك من سيقوم ببناء التطبيق و تعلم ماذا تريد و ما الأولويات لديك. في بعض التطبيقات قد تجد من الأفضل استعمال النمط NoSql و في تطبيق آخر قد تجد ال Sql أفضل. نصيحتي في حال كانت هذه أول تجربة لك ألا تفكر كثيراً و تقوم بتجربة أي قاعدة من القواعد المشهورة مثل الذي ذكرها المدرب عمر في التعليق السابق، و بعد أن يصبح لديك بعض الخبرة يمكنك محاولة تجريب قاعدة أخرى و أن تقوم بالإطلاع على الميزات و المساوئ.1 نقطة
-
الـ node ليس قاعدة بيانات وإنما سيرفر ويمكنك استخدام نوع السيرفر الذي تريده حيث ان كل السيرفرات لديها القابلية للعمل مع كل انواع قواعد البيانات. والـ node يستخدم غالباً عندما يكون هنالك عدد طلبات كثيرة على السيرفر ولكنها طلبات صغيرة الحجم (مثل تطبيقات الرسائل وغيرها) ولا يستخدم في الحالات التي تحتاج لطلبات كبيرة مثل طلبات التحميل لملفات ضخمة و المواقع التي تعرض الفيديوهات. أما قواعد البيانات فهي على نوعين SQL و NoSQL وكل منها جيد لنوع معين من البيانات وله ميزاته وعيوبه. واشهرهما هو MySQL لل SQL و mongo DB للـ NoSQL :1 نقطة
-
لديك الكثير من المواقع : مستقل ، يعتبر موقع مستقل من اكبر المنصات العربية التي تربط بين المستقل والعميل، وفي منصة مستقل في قسم المشاريع يوجد قسم كامل باسم (كتابة،تحرير ، ترجمة ولغات) وهذا القسم مليء بالمشاريع ككتابة المقالات والمحتوى والترجمة وغيرها وكلها مأجورة خمسات ، في موقع خمسات تستطيع انت تقديم خدمة الكتابة وسيأتي العملاء لكي يشترو منك على عكس موقع مستقل استكتب Blasting News هو موقع للربح من كتابة المقالات الإخبارية الأجنبية على وجه التحديد بشتى مجالاتها. Listverse هو موقع الربح من كتابة المقالات الانجليزية والتي تحتوي على قوائم من عشر حقائق غير شائعة باللغة الانجليزية Vocal هو موقع شبيه إلى حد كبير بموقع Medium الشهير، حيث يسمح لك موقع Vocal بكتابة المقالات داخل الموقع والحصول على أموال في المقابل HubPages هو موقع الربح من كتابة المقالات الانجليزية1 نقطة
-
كما ذكر المدرب معاذ 14 ساعة في الأسبوع هو وقت ليس بالقليل، و عند تقسيمه بشكل جيد يمكنك التقدم بشكل مستمر في رحلة التعلم الخاصة بك. أريد أن أضيف بعض النقاط التي ساعدتني كثيراً على تحديد متى يجب علي تعلم المزيد و متى يجب علي تطبيق ما تعلمته، أتمنى أن تساعدك أيضاً. لقد كنت أعتبر تعلم المزيد هو العملية الأساسية و التطبيق هو حدث إضافي مساعد لها (و لكن ضروري طبعاً)، فكنت أركز على التعلم و عندما أشعر بأنني لم أعد أستطع الربط في ذهني بين كافة الأفكار التي تعلمتها (بسبب كثرتها غالباً) أذهب و أقوم بتطبيق ما تعلمته، بالإضافة إلى محاولة التعديل لاختبار ما سيحدث في حال قمت بإزالة تعليمة ما أو تنسيق معين الخ.. وجدت هذه الطريقة مفيدة لي، حيث أن ذلك أفضل من وضع وقت ثابت، فقد تكون تتعلم بعض الأمور التي تعتبرها سهلة نسبياً، و بالتالي قد تجد أنه يمكنك تعلم المزيد قبل الذهاب إلى التطبيق العملي و ذلك ﻷنه من السهل الربط بين الأمور التي تعلمتها أو ﻷنها قريبة من بعضها البعض. بينما قد تكون تتعلم فكرة صعبة و لو أنه شرحها لا يأخذ أكثر من نصف ساعة مثلاً، و بالتالي قد ترغب في وضع وقت أكثر في التطبيق العملي و التجريب قبل الانتقال إلى فكرة أخرى.1 نقطة
-
عند تخزين بياناتٍ معينة بملفٍ معين أو نقلها خلال شبكةٍ معينة، سيكون من الضروري تمثيلها بطريقةٍ ما بشرط أن تَسمَح تلك الطريقة بإعادة بناء البيانات لاحقًا عند قراءة الملف أو عند تَسلُّم البيانات. رأينا بالفعل أسبابًا جيدةً تدفعنا لتفضيل التمثيلات النصية المُعتمِدة على المحارف، ومع ذلك هناك طرائقٌ كثيرةٌ لتمثيل مجموعةٍ معينةٍ من البيانات تمثيلًا نصيًا. سنُقدِّم بهذا المقال لمحةً مختصرةً عن أحد أكثر أنواع تمثيل البيانات data representation شيوعًا. تُعدّ لغة الترميز القابلة للامتداد eXtensible Markup Language -أو اختصارًا XML- أسلوبًا لإنشاء لغاتٍ لتمثيل البيانات. هناك جانبان أو مستويان بلغة XML؛ حيث تُخصِّص XML في المستوى الأول قواعد صيغة صارمةً ولكنها بسيطةً نوعًا ما، وتُعدّ أي متتالية محارف تَتبِع تلك القواعد مستند XML سليم؛ بينما تُوفِّر XML على المستوى الآخر طريقةً لإضافة المزيد من القيود على ما يُمكِن كتابته بالمستند من خلال ربط مستند XML معين بما يُعرَف باسم "تعريف نوع المستند Document Type Definition" -أو اختصارًا DTD- الذي يُخصِّص قائمةً بالأشياء المسموح بكتابتها بمستند XML. يُقال على مستندات XML السليمة المُرتبِطَة بتعريف نوع مستند معين والمُتبعِّة للقواعد التي خصَّصها ذلك التعريف "مستندات XML صالحة". يُمكِننا النظر إلى لغة XML كما لو كانت صيغةً عامةً لتمثيل البيانات؛ في حين تُخصِّص DTD الكيفية التي ينبغي بها استخدام XML لتمثيل نوعٍ معينٍ من البيانات. تتوفَّر بدائلٌ أخرى بخلاف DTD، مثل XML schemas لتعريف مستندات XML صالحة، ولكننا لن نناقشها هنا. لا يوجد شيءٌ سحريٌ بخصوص XML، فهي ليست مثالية، وتُعدُّ في الحقيقة لغةً مُسهبةً verbose ويراها البعض قبيحة، ولكنها من الناحية الأخرى مرنةٌ للغاية؛ حيث يُمكِن اِستخدَامها لتمثيل أي نوعٍ من البيانات تقريبًا. لقد صُمِّمت من البداية لتدعم جميع لغات البرمجة، والأهم من ذلك، أنها قد أصبحت بالفعل معيارًا مقبولًا على نطاقٍ واسع، فبإمكان جميع لغات البرمجة معالجة مستندات XML، بل ويتوفَّر تعريف نوع مستند DTD قياسي لوصف مختلف أنواع البيانات. هناك طرائقٌ مختلفةٌ كثيرة لتصميم لغةٍ لتمثيل مجموعةٍ من البيانات، ولكن حظت XML بشعبيةٍ واسعة، بل إنها حتى قد وجدت طريقها إلى جميع تقنيات المعلومات. على سبيل المثال، هناك لغات XML لتمثيل كُلٍ من التعبيرات الحسابية "MathML" والرموز الموسيقية "MusicXML" والجزيئات والتفاعلات الكيميائية "CML" ورسومات الفيكتور "SVG" وغيرها من المعلومات. بالإضافة إلى ذلك، تَستخِدم برامج OpenOffice والإصدارات الأحدث من Microsoft Office لغة XML بصيغ المستندات لتطبيقات معالجة النصوص وجداول البيانات spreadsheets والعروض. مثالٌ آخر هو لغة مشاركة المواقع "RSS, ATOM"، التي سهَّلت على المواقع الإلكترونية والمدونات والجرائد الإخبارية إنشاء قائمةٍ بالعناوين الأحدث المتاحة بصيغةٍ قياسيةٍ قابلةٍ للِاستخدَام بواسطة مواقع ومتصفحات الويب، وهي في الواقع نفس الصيغة المُستخدَمة لنشر المدونات الصوتية podcasts. تُعدّ XML عمومًا الصيغة الأكثر شيوعًا لتبادل المعلومات إلكترونيًا. ليس الهدف هنا هو إطلاعك على كل شيء يُمكِن معرفته عن XML، وإنما سنشرح فقط طرائقًا قليلةً يَصلُح معها استخدام XML بالبرامج؛ أي أننا لن نناقش أي شيءٍ آخر عن تعريفات نوع المستند DTD، أو مستندات XML الصالحة، وإنما سنَكتفِي باستخدام مستندات XML سليمة دون ربطها بأي تعريفاتٍ لنوع المستند DTD؛ فهي عادةً ما تكون كافيةً للعديد من الأغراض. قواعد صيغة بسيطة للغة XML إذا كنت تعرف لغة HTML -اللغة المُستخدَمة لكتابة صفحات الإنترنت-، فستبدو لغة XML مألوفةً بالنسبة لك، حيث تشبه مستندات XML كثيرًا مستندات HTML. لا تُعدّ لغة HTML هي نفسها لغة XML؛ فهي لا تَتبِع جميع قواعد الصيغة الصارمة الخاصة بلغة XML، ولكن الأفكار الأساسية هي نفسها. نعرض فيما يلي مثالًا قصيرًا على مستند XML سليم: <?xml version="1.0"?> <simplepaint version="1.0"> <background red='1' green='0.6' blue='0.2'/> <curve> <color red='0' green='0' blue='1'/> <symmetric>false</symmetric> <point x='83' y='96'/> <point x='116' y='149'/> <point x='159' y='215'/> <point x='216' y='294'/> <point x='264' y='359'/> <point x='309' y='418'/> <point x='371' y='499'/> <point x='400' y='543'/> </curve> <curve> <color red='1' green='1' blue='1'/> <symmetric>true</symmetric> <point x='54' y='305'/> <point x='79' y='289'/> <point x='128' y='262'/> <point x='190' y='236'/> <point x='253' y='209'/> <point x='341' y='158'/> </curve> </simplepaint> يُعدّ السطر الأول بالأعلى اختياريًا، حيث يُشير ببساطةٍ إلى أن ما يليه هو مستند XML. قد يتضمَّن هذا السطر معلوماتٍ أخرى أيضًا، مثل الترميز المُستخدَم لترميز محارف المستند إلى صيغةٍ ثنائية. وقد يتضمَّن المستند سطرًا للموجه "DOCTYPE" لتحديد تعريف نوع المستند. يتكوَّن المستند بخلاف السطر الأول من مجموعةٍ من العناصر elements والسمات attributes والمحتويات النصية. يبدأ أي عنصرٍ بوسم tag، مثل <curve> وينتهي بوسم الغلق المقابل، مثل </curve>، ونجد محتويات العنصر بين هذين الوسمين، والتي يُمكِن أن تتكوَّن من نصٍ وعناصرٍ متداخلة أخرى. يُعدّ المحتوى النصي الوحيد بالمثال السابق هو القيمة true أو false بالعنصر <symmetric>. إذا لم يحتوِ عنصرٌ معينٌ على أي شيء، يُمكِننا دمج وسميه للفتح والغلق بوسمٍ واحدٍ فارغ بكتابة الاختصار <point x='83' y='96'/> بدلًا من <point x='83' y='96'></point>. لاحِظ استخدام "/" قبل "<". قد يتضمَّن الوسم عِدّة سمات، مثل x و y بالوسم <point x='83' y='96'/>، و version بالوسم <simplepaint version="1.0">. قد يتضمَّن المستند أشياءً قليلةً أخرى، مثل التعليقات ولكننا لن نناقشها هنا. ينبغي لأي مؤلف مستند XML سليم أن يختار أسماء الوسوم والسمات، وبطبيعة الحال عليه اختيار أسماءٍ ذات معنًى مفهوم للقارئ. في المقابل، إذا كان المستند يعتمد على تعريف نوع مستند DTD معين، فإن مؤلف التعريف هو من يختار أسماء الوسوم. يجب على أي مستند XML سليم أن يَتبِّع مجموعةً صارمةً من قواعد الصياغة syntax، نُلخِّص أهمها فيما يلي: تُميِّز أسماء الوسوم والسمات بمستندات XML بين حالة الأحرف case sensitive؛ فقد تتكوَّن الأسماء من مجموعةٍ من الأحرف والأرقام وبعض المحارف الأخرى، ولكن لا بُدّ أن تبدأ بحرف. ليس للفراغات ومحرف نهاية السطر أي أهمية إلا إذا وقعت بالمحتويات النصية؛ فعند كتابة وسمٍ معينٍ، ولم يَكُن هذا الوسم فارغًا، فيجب إذًا أن يُقابِله وسم غلق؛ ويَعنِي ذلك أنه إذا تداخلت عدة عناصرٍ مع بعضها، فيجب أن يكون التداخل سليمًا. بتعبيرٍ آخر، إذا تضمَّن عنصرٌ معينٌ وسمًا، فيجب أن يَقع وسم غلقه ضمن نفس العنصر. لا بُدّ أن يحتوي أي مستندٍ على عنصر جذر root، والذي يحتوي بدوره على جميع العناصر الأخرى. لاحِظ أن اسم الوسم المُمثِّل لعنصر الجذر بالمثال السابق، هو simplepaint. لا بُدّ أن يكون لأي سمةٍ قيمة، والتي ينبغي أن تكون محاطةً بعلامتي اقتباس إما مفردة أو مزدوجة. في حالة اِستخدَام المحارف الخاصة > و & بقيمةٍ لسمة أو بمحتوى نصي، فيجب أن تُكْتَب على النحو التالي > و ". أمثلة أخرى على ذلك، هي > و " و '، والتي تُمثِّل > وعلامة اقتباسٍ مزدوجة وعلامة اقتباسٍ مفردة على الترتيب. يُمكِن تعريف المزيد بتعريف DTD. يُعدّ ما سَبَق مقدمةً سريعةً عن مستندات XML، والتي ربما لن تساعدك على فهم كل شيء تقابله بمستند XML، ولكنها ستُمكِّنك على الأقل من تصميم مستندات XML سليمة لتمثيل بعض بنى البيانات data structures المُستخدَمة ببرامج جافا. العمل مع شجرة DOM صمَّمنا في الأعلى مثال XML لتخزين معلوماتٍ عن رسومٍ بسيطة يَرسِمها المُستخدِم، واعتمدنا على البرنامج التوضيحي SimplePaint2.java من مقال مفهوم المصفوفات الديناميكية (ArrayLists) في جافا فيما هو مُتعلِّقٌ برسم تلك الرسوم. سنناقش بهذا المقال نسخةً أخرى من نفس البرنامج، والتي يُمكِنها حفظ رسوم المُستخدِم بملف بياناتٍ معتمِدٍ على صيغة XML. يُمكِنك الإطلاع على شيفرة النسخة الجديدة من SimplePaintWithXML.java. سنَستخدِم مستند XML التوضيحي الذي عرضناه بالأعلى ضمن هذا البرنامج. في الحقيقة، لقد صمَّمنا هذا المستند بحيث يحتوي على جميع البيانات المطلوبة لإعادة إنشاء الكائن المُمثِّل للرسمة، والذي ينتمي للصنف SimplePaint؛ حيث يتضمَّن المستند على سبيل المثال معلوماتٍ عن لون خلفية الصورة وكذلك قائمةً بالمنحنيات التي رَسَمها المُستخدِم. لاحِظ احتواء كل عنصر <curve> على بيانات كائنٍ من النوع CurveData. من السهل كتابة برنامج يُخرِج البيانات بصيغة XML، مع الحرص طبعًا على اتباع جميع قواعد صيغة XML، حيث تبيّن الشيفرة التالية الطريقة التي يَستخدِمها الصنف SimplePaintWithXML لإرسال بيانات رسمةٍ من النوع SimplePaint إلى out من النوع PrintWriter. يَنتُج عن ذلك مستند XML بنفس هيئة المثال المُوضَح بالأعلى: out.println("<?xml version=\"1.0\"?>"); out.println("<simplepaint version=\"1.0\">"); out.println(" <background red='" + backgroundColor.getRed() + "' green='" + backgroundColor.getGreen() + "' blue='" + backgroundColor.getBlue() + "'/>"); for (CurveData c : curves) { out.println(" <curve>"); out.println(" <color red='" + c.color.getRed() + "' green='" + c.color.getGreen() + "' blue='" + c.color.getBlue() + "'/>"); out.println(" <symmetric>" + c.symmetric + "</symmetric>"); for (Point2D pt : c.points) out.println(" <point x='" + pt.getX() + "' y='" + pt.getY() + "'/>"); out.println(" </curve>"); } out.println("</simplepaint>"); قراءة البيانات من مستند XML إلى البرنامج مرةً أخرى هي عمليةٌ أخرى تمامًا، حيث ينبغي تحليل parse المستند واستخراج البيانات منه؛ لنتمكَّن من إعادة إنشاء بنية البيانات المُمثِلة للمستند، وهو ما يتطلّب الكثير من العمل. تُوفِّر جافا لحسن الحظ واجهة برمجة تطبيقات قياسية standard API لتحليل مستندات XML ومعالجتها، وهي تُوفِّر في الواقع واجهتين ولكننا سنتعامل مع واحدةٍ منهما فقط. يتكوَّن أي مستند XML سليم من بنيةٍ معروفةٍ مكوَّنة من مجموعةٍ من العناصر elements مُتضمَّنةً مجموعةً من السمات attributes؛ والعناصر المتداخلة؛ والمحتويات النصية. يُمكِننا إنشاء بنية بياناتٍ مكافئةً لبنية المستند ومحتوياته في ذاكرة الحاسوب، حيث تتوفَّر الكثير من الطرائق لذلك، ولكن يُعدّ تمثيل نموذج كائن المستند Document Object Model -أو اختصارًا DOM- أكثرها شيوعًا؛ حيث يُخصِّص هذا النموذج طريقةً لبناء بنية بياناتٍ مكافئة لمستندات XML؛ كما أنه يُعرِّف مجموعةً من التوابع methods القياسية، التي تَسمَح باسترجاع البيانات الموجودة ضمن تلك البنية. تُعدّ تلك البنية أشبه ما تكون بشجرةٍ تُكافئ بنيتها بنية المستند، حيث تتكوَّن الشجرة من أنواعٍ مختلفة من العُقد nodes المُستخدَمة لتمثيل العناصر والسمات والنصوص، كما قد تحتوي على أنواعٍ آخرى من العُقد لتمثيل جوانبٍ أخرى من XML. سنُركز فقط على العقد المُمثِّلة للعناصر بسبب عدم القدرة على معالجة السمات والنصوص مباشرةً دون معالجة ما يُقابِلها من عُقد. يُمكِّنك البرنامج التوضيحي XMLDemo.java من التعامل مع كُلٍ من XML و DOM. يتضمَّن البرنامج صندوقًا نصيًا حيث يُمكِنك كتابة مستند XML، كما يحتوي على مستند XML توضيحي من هذا المقال افتراضيًا. إذا ضغطت على الزر "Parse XML Input"، سيقرأ البرنامج المستند المكتوب بالصندوق، وسيحاول بناء تمثيل DOM له. إذا لم تَكْن المُدْخلات مُمثِّلةً لمستند XML سليم، فستظهر رسالة خطأ؛ أما إذا كانت سليمة، فسيجتاز البرنامج تمثيل DOM بالكامل، وسيَعرِض قائمةً بكل العناصر والسمات والمحتويات النصية التي سيُقابِلها. يَستخدِم البرنامج بعض التقنيات لمعالجة XML، ولكننا لن نناقشها هنا. يُمكِننا إنشاء تمثيل DOM لمستند XML باستخدام التعليمتين التاليتين. إذا كان selectedFile متغيرًا من النوع File يُمثِّل مستند XML، فسيكون xmldoc من النوع Document: DocumentBuilder docReader = DocumentBuilderFactory.newInstance().newDocumentBuilder(); xmldoc = docReader.parse(selectedFile); تَفتَح الشيفرة السابقة الملف، وتقرأ محتوياته، ثم تَبنِي تمثيل DOM. ستَجِد الصنفين DocumentBuilder و DocumentBuilderFactory بحزمة javax.xml.parsers. يُحاوِل التابع docReader.parse() إجراء العملية، ويُبلِّغ عن اعتراضٍ إذا لم يتمكَّن من قراءة الملف أو إذا لم يحتوِ الملف على مستند XML صالح. في المقابل، إذا نجح التابع، فإنه يعيد كائنًا يُمثِّل كامل المستند. تُعدّ هذه العملية معقدةً بالتأكيد، ولكنها بُرمجَت بالكامل مرةً واحدةً، وضُمِّنَت بتابعٍ يُمكِنك اِستخدَامه بسهولة بأي برنامج جافا، وهو ما يُمثِّل إحدى فوائد الاعتماد على صيغةٍ قياسية. يُمكِنك الإطلاع على تعريف بنية البيانات DOM بحزمة org.w3c.dom، والتي تحتوي على أنواع بياناتٍ مختلفة لتمثيل مستند XML بالكامل؛ وكذلك لتمثيل العقد الموجودة بالمستند على حدى. يشير الاسم "org.w3c" إلى اتحاد شبكة الويب العالمية World Wide Web Consortium -أو اختصارًا W3C، والمسؤولة عن تنظيم المعايير القياسية لتقنيات الويب. يُعدّ تمثيل DOM مثل XML معيارًا عامًا؛ أي لا يختص بلغة جافا دون غيرها. سنحتاج بهذا المثال أنواع البيانات التالية Document و Node و Element و NodeList، والمُعرَّفة جميعًا على أنها واجهات interfaces لا أصناف، ولكن هذا غير مهم. سنَستخدِم التوابع المُعرَّفة بتلك الأنواع للوصول إلى البيانات الموجودة بتمثيل DOM لمستند XML. يعيد التابع docReader.parse() قيمةً من النوع Document، والتي كانت xmldoc في المثال السابق، وهي تُمثِّل مستند XML بالكامل. سنحتاج إلى التابع التالي فقط من هذا الصنف. إذا كان xmldoc من النوع Document، يُمكِننا كتابة ما يلي: xmldoc.getDocumentElement() يُعيد هذا التابع قيمةً من النوع Element تُمثِّل عنصر الجذر root الخاص بالمستند؛ وهوالعنصر الموجود بأعلى مستوى بالمستند كما ذكرنا مُسبقًا، ويتضمَّن كافة العناصر الأخرى. يتكوَّن عنصر الجذر بمستند XML الخاص بالمثال السابق من هذا المقال من الوسمين <simplepaint version="1.0"> و </simplepaint>، وكل ما هو موجودٌ بينهما. تُمثَّل العناصر الواقعة داخل عنصر الجذر باستخدام عقد nodes، والتي تُعدّ بمثابة أبناء عقدة الجذر. تتضمَّن كائنات النوع Element مجموعةً من التوابع المفيدة، والتي سنستعرِض بعضًا منها فيما يلي. إذا كان element من النوع Element، يُمكِننا استخدام التوابع التالية: element.getTagName(): يُعيد سلسلةً نصيةً من النوع String للاسم المُستخدَم بالوسم الخاص بالعنصر؛ حيث سيُعيد على سبيل المثال السلسلة النصية "curve" للعنصر <curve>. element.getAttribute(attrName): إذا كان attrName اسم سمةٍ في العنصر، سيُعيد التابع قيمة تلك السمة. على سبيل المثال، يعيد الاستدعاء element.getAttribute("x") السلسلة النصية "83" للعنصر <point x="83" y="42"/>، وتكون القيمة المعادة من النوع String دائمًا حتى لو كانت السمة تُمثِّل قيمة عددية. إذا لم يحتوِ عنصرٌ معين على سمةٍ للاسم المُخصَّص، فسيعيد التابع سلسلةً نصيةً فارغة. element.getTextContent(): يُعيد سلسلةً نصيةً من النوع String تحتوي على المحتوى النصي الموجود بالعنصر، بما في ذلك محتوى العناصر الأخرى الواقعة ضمن العنصر. element.getChildNodes(): يعيد قيمةً من النوع NodeList تحتوي على جميع العُقد الأبناء لذلك العنصر. تتضمَّن القائمة العقد المُمثِلة لأي عنصرٍ آخر أو محتوى نصي (إلى جانب أنواع أخرى من العقد) مُتداخِل مباشرةً مع العنصر. يَسمَح التابع getChildNodes() باجتياز بنية البيانات DOM بالكامل بدءًا من عنصر الجذر، مرورًا بأبنائه، وأبناء أبنائه، وهكذا. يتوفَّر تابعٌ آخر يعيد جميع سمات العنصر، ولكننا لن نَستخدِمه هنا. element.getElementsByTagName(tagName): يُعيد قيمةً من النوع NodeList تحتوي على جميع العُقد المُمثِّلة لعناصر واقعةٍ داخل element، والتي لها نفس اسم الوسم المُخصَّص. يتضمَّن ذلك العناصر الواقعة بأي مستوى داخل element، وليس فقط تلك المتصلة مباشرةً معه. يَسمَح التابع getElementsByTagName() بالوصول إلى بيانات مُحدَّدة ضمن المستند. يُمثِّل كائنٌ من النوع NodeList قائمةً من العقدة من النوع Node، ولكنه لا يَستخدِم واجهة برمجة التطبيقات الخاصة بالقوائم والمُعرَّفة بإطار عمل جافا للتجميعات. يُعرِّف الصنف NodeList بدلًا من ذلك التابعين التاليين: nodeList.getLength() و nodeList.item(i)؛ حيث يُعيد الأول عدد العقد ضمن القائمة؛ بينما يُعيد الثاني العقدة الموجودة بموضع i، والذي تتراوح قيمه من 0 حتى nodeList.getLength() - 1. يُعيد التابع nodeList.get() قيمةً من النوع Node، والتي يُمكِن تحويلها type-cast إلى نوعٍ مُخصّصٍ من العقد قبل استخدامها. بناءً على هذه المعلومات، يُمكِنك إجراء أغلب أنواع العمليات الممكنة على تمثيلات DOM. لنفحص الآن بعض الشيفرة. لنفترض أنه وبينما تعالج إحدى المستندات، قد توصلت إلى عقدةٍ من النوع Element تُمثِّل العنصر التالي: <background red='1' green='0.6' blue='0.2'/> قد يقابلنا العنصر السابق إما أثناء اجتياز المستند باستخدام getChildNodes() أو نتيجةً لاستدعاء التابع getElementsByTagName("background"). علينا الآن إعادة إنشاء بنية البيانات التي يُمثِّلها المستند، والتي يُعدّ هذا العنصر جزءًا من بياناتها؛ حيث يُمثِل لون الخلفية تحديدًا بواسطة ثلاث سمات attributes تُمثِّل مكوّنات اللون الأحمر والأخضر والأزرق. إذا كان element متغيرًا يُشير إلى تلك العقدة، يُمكِننا استرجاع اللون بكتابة ما يَلي: double r = Double.parseDouble( element.getAttribute("red") ); double g = Double.parseDouble( element.getAttribute("green") ); double b = Double.parseDouble( element.getAttribute("blue") ); Color bgColor = Color.color(r,g,b); لنفترض الآن أن element يشير إلى العقدة المُمثِّلة للعنصر التالي: <symmetric>true</symmetric> يُمثِل element في تلك الحالة قيمة مُتغيّر من النوع المنطقي boolean، ولكنها رُمزَّت كأنها محتوًى نصي للعنصر. يُمكِننا استرجاع تلك القيمة من العنصر بكتابة ما يَلي: String bool = element.getTextContent(); boolean symmetric; if (bool.equals("true")) symmetric = true; else symmetric = false; لنفكر الآن بمثالٍ يَستخدِم كائنًا من الصنف NodeList. إذا واجهنا العنصر التالي الذي ينبغي تمثيله بقائمة عناصر تنتمي للصنف Point2D: <pointlist> <point x='17' y='42'/> <point x='23' y='8'/> <point x='109' y='342'/> <point x='18' y='270'/> </pointlist> لنفترض أن element يشير إلى العقدة المُمثِّلة للعنصر <pointlist>، علينا الآن إنشاء قائمةٍ من النوع ArrayList<Point2D> لتمثيله، حيث تجتاز الشيفرة التالية قائمة الصنف NodeList المُتضمِّنة لعقد أبناء العنصر على النحو التالي: ArrayList<Point2D> points = new ArrayList<>(); NodeList children = element.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node child = children.item(i); // أحد عقد أبناء العنصر if ( child instanceof Element ) { Element pointElement = (Element)child; // One of the <point> elements. int x = Integer.parseInt( pointElement.getAttribute("x") ); int y = Integer.parseInt( pointElement.getAttribute("y") ); // أنشئ النقطة التي يُمثِلها pointElement Point2D pt = new Point2D(x,y); points.add(pt); // أضف النقطة إلى قائمة النقاط } } تُعدّ جميع عناصر <point> الواقعة داخل العنصر <pointlist> أبناءً له. يجب أن نَستخدِم تعليمة if -كما بالأعلى- نظرًا لإمكانية احتواء العنصر على أبناء تنتمي لأصناف أخرى غير الصنف Element، والتي نحن في الواقع غير مهتمين بمعالجتها ضمن هذا المثال. يُمكِننا توظيف كل تلك التقنيات لكتابة تابعٍ يقرأ ملف الدْخَل بالبرنامج التوضيحي SimplePaintWithXML.java. عندما نُنشِئ بنية بياناتٍ لتمثيل ملف XML، يُفضَّل أن نبدأ ببنية بياناتٍ افتراضية، والتي يُمكِننا تعديلها، والإضافة إليها بينما نجتاز شجرة DOM المُمثِلة للملف. في الواقع، هذه العملية ليست سهلة نوعًا ما، ولذلك حاول أن تقرأها بعناية: Color newBackground = Color.WHITE; ArrayList<CurveData> newCurves = new ArrayList<>(); Element rootElement = xmldoc.getDocumentElement(); if ( ! rootElement.getNodeName().equals("simplepaint") ) throw new Exception("File is not a SimplePaint file."); String version = rootElement.getAttribute("version"); try { double versionNumber = Double.parseDouble(version); if (versionNumber > 1.0) throw new Exception("File requires a newer version of SimplePaint."); } catch (NumberFormatException e) { } NodeList nodes = rootElement.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { if (nodes.item(i) instanceof Element) { Element element = (Element)nodes.item(i); if (element.getTagName().equals("background")) { double r = Double.parseDouble(element.getAttribute("red")); double g = Double.parseDouble(element.getAttribute("green")); double b = Double.parseDouble(element.getAttribute("blue")); newBackground = Color.color(r,g,b); } else if (element.getTagName().equals("curve")) { CurveData curve = new CurveData(); curve.color = Color.BLACK; curve.points = new ArrayList<>(); newCurves.add(curve); NodeList curveNodes = element.getChildNodes(); for (int j = 0; j < curveNodes.getLength(); j++) { if (curveNodes.item(j) instanceof Element) { Element curveElement = (Element)curveNodes.item(j); if (curveElement.getTagName().equals("color")) { double r = Double.parseDouble(curveElement.getAttribute("red")); double g = Double.parseDouble(curveElement.getAttribute("green")); double b = Double.parseDouble(curveElement.getAttribute("blue")); curve.color = Color.color(r,g,b); } else if (curveElement.getTagName().equals("point")) { double x = Double.parseDouble(curveElement.getAttribute("x")); double y = Double.parseDouble(curveElement.getAttribute("y")); curve.points.add(new Point2D(x,y)); } else if (curveElement.getTagName().equals("symmetric")) { String content = curveElement.getTextContent(); if (content.equals("true")) curve.symmetric = true; } } } } } } backgroundColor = newBackground; curves = newCurves; يُمكِنك الإطلاع على كامل الشيفرة المصدرية في الملف SimplePaintWithXML.java. تطوَّرت XML لتُصبِح واحدةً من أهم التقنيات المُستخدَمة لتطوير بعض أعقد التطبيقات، وهناك مع ذلك بعض الأفكار الأساسية البسيطة التي يَسهُل تطبيقها بجافا. بمجرد إطلاعك على أساسيات XML، يُمكِنك استخدامها بفعالية ضمن برامج جافا الخاصة بك. ترجمة -بتصرّف- للقسم Section 5: A Brief Introduction to XML من فصل Chapter 11: Input/Output Streams, Files, and Networking من كتاب Introduction to Programming Using Java. اقرأ أيضًا المقال السابق: تواصل تطبيقات جافا عبر الشبكة الدليل السريع للغة البرمجة Java اكتب برنامجك الأول بلغة جافا1 نقطة
-
الكتاب ممتاز وجميل وقد أعجبني جدًا. الكتاب ليس ترجمة بالكامل بل معظمه تأليف ولهذا تلحظ أنّ أسلوب الكتابة وطريقة التعامل مع المصطلحات سلسان للغاية وكأنّك تقرأ كتاب عربي أصلي. يشرح الكتاب كذلك كلّ ما يحتاجه المرء لبدء استخدام قاعدة PostgreSQL بأسلوب مفصّل وعملي. أعجبني كذلك تصميم الكتاب حيث المحتوى غير محشو بكثرة في كلّ صفحة بل هو مُرتاح والحواشي مرخيّة، وهو ما يجعل عملية القراءة أكثر متعة. في المرّة المقبلة التي يطلب منها أحدٌ منّي مصادر لتعلّم PostgreSQL سأعطيه هذا الكتاب فقط. شكرًا جزيلًا على إخراج الكتاب.1 نقطة