نظرة عامة: يتم استخدام لغة التوصيف القابلة للتوسيع (XML) بسرعة في الصناعة، وقد أصبحت معيارًا مستخدمًا على نطاق واسع لوصف البيانات وتبادلها بتنسيق مستقل عن النظام الأساسي واللغة والبروتوكول. يمكن استخدام XML ومواصفاته المساعدة لوصف تمثيل المستند للبيانات، ووصف القيود المفروضة على أنواع مستندات XML، ووصف الروابط بين مستندات XML والموارد، ووصف التحويل والتنسيق التلقائي لمستندات XML.
كيفية تطوير مكتبة العلامات المخصصة؟
لقد كنت أستخدم برمجة JSP و ASP لفترة طويلة، ومن بين طريقتي البرمجة من جانب الخادم، أشعر بشكل متزايد أن JSP أقوى بكثير. ناهيك عن أي شيء آخر، فإن مكتبة العلامات الخاصة بـ JSP هي السبب وراء اختياري لـ JSP كأداة تطوير تطبيقات الويب المفضلة من جانب الخادم. لماذا؟ لأنه: سرعة الصيانة والتطوير. ضمن صفحة خادم واحدة، يمكنك مزج ومطابقة أساليب وكائنات البرنامج النصي المختلفة. مثل "الملموس"، فإن هذا المزيج يجعل البرمجة النصية من جانب الخادم قوية ويسمح للمبرمجين من جانب الخادم بتصميم صفحات ويب مرنة وديناميكية للغاية، ومع ذلك، فإن هذا المزيج المجاني له أيضًا عيوبه، وهي أنه من الصعب صيانته. خاصة مع تزايد حجم المشروع، نظرًا لأن المنتج النهائي تتم صيانته بواسطة مصمم ويب تقليدي، والأسوأ من ذلك، أن سرعة التطوير تزداد مع زيادة تعقيد الكود، وسوف تصبح أبطأ ولا تساعد على تطوير الوسائط و تطبيقات الويب واسعة النطاق، بمجرد تطويرها، سيظل الموقع بحاجة إلى العثور على مبرمجين مؤهلين للحفاظ على هذه الرموز المعقدة إلى حد ما.
ولحسن الحظ، يوفر JSP حلاً جيدًا. توفر مكتبات العلامات طريقة سهلة لإنشاء كتلة من التعليمات البرمجية قابلة لإعادة الاستخدام. بمجرد تصميم مكتبة العلامات، يمكن استخدامها مرة أخرى في العديد من المشاريع. والأمر الأكثر ملاءمة هو أنه، على عكس COM وJ2EE، لا تحتاج إلى تعلم أي مهارات أخرى لإنشاء مكتبة علامات! طالما أنك تعرف كيفية كتابة JSP، يمكنك إنشاء مكتبة علامات. يمكن لمكتبات العلامات أيضًا تحسين صيانة تطبيقات الويب. هذه واجهة XML بسيطة بفضل العلامات المخصصة لصفحة JSP. بهذه الطريقة، يمكن لمصممي الويب إنشاء تطبيقات ويب JSP دون معرفة أي معرفة بـ JSP. يعد تطوير الويب المفتوح هذا فعالًا جدًا لعمليات الفريق. يمكن لمبرمجي JSP إنشاء علامات مخصصة ووحدات رمز خلفية، بينما يمكن لمصممي الويب استخدام علامات مخصصة لإنشاء تطبيقات الويب والتركيز على تصميم الويب.
1. تعريف مكتبة العلامات يمكن اعتبار مكتبة علامات JSP (وتسمى أيضًا المكتبة المخصصة) مجموعة من الأساليب لإنشاء نصوص برمجية مستندة إلى XML، والتي يدعمها JavaBeans. من الناحية النظرية، تعد مكتبات العلامات عبارة عن بنيات برمجية بسيطة جدًا وقابلة لإعادة الاستخدام.
أمثلة العلامات وصفحات HTML التي تجري تحويل XML/XSL
<%@ taglib uri=" http://www.jspinsider.com/jspkit/JAXP " prefix="JAXP"%>
ج:/xml/example.xml
c:/xml/example.xsl
في هذا المثال، باستخدام علامات بسيطة للوصول إلى التعليمات البرمجية الأكثر قوة خلف الكواليس، يتم تحميل XML وإنشاء نتيجة من خلال ملف XSL وإرسالها إلى العميل، كل ذلك عبر يتم ذلك باستخدام مكالمة علامة بسيطة.
تفتح العلامات المخصصة الباب لإنشاء تعليمات برمجية قابلة لإعادة الاستخدام بسهولة في مشاريع JSP. كل ما تحتاجه هو مكتبة العلامات ووثائقها.
2. مكونات العلامات على الرغم من أن مكتبة العلامات سهلة الاستخدام للغاية، إلا أن إنشاء تصميم داخلي لدعم مكتبة العلامات أمر معقد للغاية، على الأقل أكثر تعقيدًا من إنشاء JavaBean بسيط. يأتي التعقيد من حقيقة أن مكتبة العلامات تتكون من عدة أجزاء. ومع ذلك، ما عليك سوى معرفة Java وJSP.
تتكون العلامة البسيطة من العناصر التالية:
⑴ JavaBeans: للحصول على المزايا المتأصلة الموجهة للكائنات في Java، يجب وضع التعليمات البرمجية القابلة لإعادة الاستخدام في حاوية تعليمات برمجية مستقلة. JavaBeans هذه ليست جزءًا من مكتبة العلامات. ولكنها الكتلة الأساسية من التعليمات البرمجية التي تستخدمها قاعدة التعليمات البرمجية الخاصة بك لأداء المهام ذات الصلة.
⑵ معالجة العلامات: هذا هو الجوهر الحقيقي لمكتبة العلامات. سيشير معالج العلامات إلى أي موارد يحتاجها (JavaBeans الخاص بك) ويصل إلى جميع المعلومات المتعلقة بصفحة JSP الخاصة بك (كائن pageContext). ستنقل صفحة JSP أيضًا جميع سمات العلامة التي تم تعيينها ومحتويات نص العلامة على صفحة JSP إلى معالج العلامات. بعد انتهاء معالج العلامات من المعالجة، سيرسل المخرجات مرة أخرى إلى صفحة JSP الخاصة بك للمعالجة.
⑶ وصف مكتبة العلامات (ملف tld): هذا ملف XML بسيط يسجل السمات والمعلومات وموقع معالج العلامات. تستخدم حاوية JSP هذا الملف لمعرفة مكان وكيفية استدعاء مكتبة العلامات.
⑷ ملف web.xml الخاص بموقع الويب: هذا هو ملف التهيئة لموقع الويب الخاص بك. في هذا الملف، يمكنك تحديد العلامات المخصصة المستخدمة في موقع الويب، وملف tld الذي يتم استخدامه لوصف كل علامة مخصصة.
⑸ ملف التوزيع (ملف WAR أو JAR): إذا كنت تريد إعادة استخدام العلامات المخصصة، فأنت بحاجة إلى طريقة لنقلها من مشروع إلى آخر. يعد تجميع مكتبة العلامات في ملف JAR طريقة بسيطة وفعالة.
⑹ قم بإنشاء إعلان لمكتبة العلامات في ملف JSP الخاص بك: إنه أمر بسيط للغاية. إذا كنت تريد استخدام هذه العلامة، فما عليك سوى الإعلان عنها على الصفحة، وبعد ذلك يمكنك استخدامها في أي مكان في صفحة JSP.
يبدو أن هناك الكثير من العمل الذي يتعين القيام به، لكنه في الواقع ليس بهذه الصعوبة. لا يتعلق الأمر بالترميز، بل يتعلق بتنظيم القطع بشكل صحيح. ومع ذلك، فإن هذه الطبقات مهمة لأنها تجعل استخدام الملصق مرنًا وأسهل في النقل. والأهم من ذلك، أن هذه الطبقات موجودة لأتمتة عملية إنشاء العلامات من خلال JSP IDE (بيئة التطوير المتكاملة JSP). من المتوقع أن تتمكن بيئة تطوير JSP IDE المستقبلية من إكمال معظم أعمال إنشاء علامة مخصصة تلقائيًا، بحيث تحتاج فقط إلى كتابة التعليمات البرمجية ومعالجة العلامات.
ملاحظة: يحدد معالج العلامات علامة مخصصة واحدة فقط؛ مكتبة العلامات عبارة عن مجموعة من معالجات العلامات المتعددة التي تتعامل مع نفس المهمة.
3. قم بإنشاء العلامات الخاصة بك: سيعلمك ما يلي خطوة بخطوة كيفية إنشاء علامات مخصصة، والمثال المحدد هو توسيع JSP بحيث يكون له وظيفة تشفير HTML الخاصة به. تستبدل هذه الميزة كافة الأحرف < و > برمز HTML. يمكن تمديده بسهولة للقيام بمعالجة الترميز الأخرى. للتبسيط، يشرح هذا المثال فقط العناصر الأساسية لإنشاء علامة مخصصة.
⑴ إنشاء JavaBean
يجب وضع أي جزء قابل لإعادة الاستخدام من التعليمات البرمجية الخاصة بك في JavaBean. يعد هذا أمرًا مهمًا لأنك ستستخدم هذا الرمز غالبًا في مكان آخر من المشروع. أي رمز يتم وضعه داخل معالج العلامات لا يمكن إعادة استخدامه خارج العلامة، لذلك من المهم عزل أجزاء التعليمات البرمجية القابلة لإعادة الاستخدام. في هذا المثال، يعد المنطق المشفر لـ HTML شائعًا وبالتالي يتم وضعه في JavaBean.
⑵ ترميز HTML JavaBean
/* HTML_Format.Java */
الطبقة العامة HTML_Format تمتد الكائن تنفذ Java.io.Serializable {
/** إنشاء تنسيق HTML_Format جديد */
HTML_Format العامة () {}
/** استبدل جميع الأحرف < و > في سلسلة بترميز HTML للاستجابة */
سلسلة HTML_Encode العامة (سلسلة as_data)
{
int li_len = as_data. length();
/*طول المخزن المؤقت للسلسلة أطول من السلسلة الأصلية*/
StringBuffer lsb_encode = new StringBuffer(li_len + (li_len/10));
/* تكرار لاستبدال كافة الأحرف < و > */
ل(int li_count = 0; li_count <li_len; li_count++)
{ String ls_next = String.valueOf(as_data.charAt(li_count));
إذا (ls_next.equals("<")) ls_next = "<";
إذا (ls_next.equals(">")) ls_next = ">";
lsb_encode.append(ls_next);
}
return(lsb_encode.toString());
}
}
⑶ قم بإنشاء معالج العلامات يستخدم معالج العلامات الكود التالي:
معالج علامات ترميز HTML
استيراد Java.io.IOException؛
import Javax.servlet.jsp.*;
import Javax.servlet.jsp.tagext.*;
تعمل الفئة العامة HTML_FormatTag على توسيع BodyTagSupport
{
/* 1} سيتم استدعاء هذه الوظيفة في نهاية العلامة*/
public int doEndTag() يرمي JspTagException
{
يحاول
{ /* 2} احصل على النص الموجود في التسمية */
BodyContent l_tagbody = getBodyContent();
سلسلة ls_output = "";
/* 3} إذا كان نص العلامة يحتوي على نص، فقم بمعالجته */
إذا (l_tagbody != فارغة)
{ HTML_Format l_format = new HTML_Format();
/* 3a} تحويل محتوى نص العلامة إلى سلسلة */
String ls_html_text = l_tagbody.getString();
ls_output = l_format.HTML_Encode(ls_html_text);
}
/* 4}أعد كتابة النتائج إلى دفق البيانات*/
pageContext.getOut().write(ls_output.trim());
}
قبض (IOException ه)
{رمي JspTagException الجديد("خطأ في العلامة:" + e.toString());
}
/* دع JSP يستمر في معالجة محتوى الصفحات التالية*/
إرجاع EVAL_PAGE؛
}
}
هذه المعالجة بسيطة جدًا، وتتضمن ما يلي:
o اقرأ النص بين بداية العلامة ونهايتها o اتصل بوظيفة تشفير html o قم بإرجاع النتيجة إلى صفحة JSP.
⑷ يحتاج إنشاء واصف العلامة إلى وصف العلامة المخصصة حتى يعرف النظام كيفية معالجتها. لاحقة ملف الوصف هذا هي .tld، وعادة ما يكون اسمه هو نفس معالج العلامات، ويتم تخزينه في الدليل "/WEB-INF/".
واصف علامة ترميز HTML
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
عامة "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN"
" http://Java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd ">
<تاغليب>
<TLIBVERSION>1.0</TLIBVERSION>
<JSPVERSION>1.1</JSPVERSION>
<SHORTNAME>HTML_FormatTag</SHORTNAME>
<URI></URI>
<INFO>علامة ترميز HTML </INFO>
<علامة>
<NAME>HTMLEncode</NAME>
<TAGCLASS>HTML_FormatTag</TAGCLASS>
<INFO>تشفير HTML</INFO>
</تاغ>
</TAGLIB>
⑸ قم بتحديث ملف Web XML لإخبار حاوية JSP الآن باستخدام مكتبة العلامات. للقيام بذلك، تحتاج إلى تعديل ملف web.xml، وعلى وجه التحديد، تحتاج إلى إضافة مشروع taglib لتسجيل مكتبة العلامات. والأهم من ذلك، تعيين URI للعلامة. يعد URI مرجعًا فريدًا ينطبق فقط على هذه العلامة المحددة الموجودة على موقع الويب. من الممارسات الجيدة استخدام عنوان URL الكامل أو اسم الحزمة لضمان التفرد حيث يمكن استخدام العلامة على مواقع ويب مختلفة. تم تبسيط هذا المثال.
تعديل ملف web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE تطبيق الويب
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
" http://Java.sun.com/j2ee/dtds/web-app_2.2.dtd ">
<تطبيق الويب>
<تاغليب>
<TAGLIB-URI>
HTMLEncode
</TAGLIB-URI>
<موقع العلامة>
/WEB-INF/HTML_FormatTag.tld
</TAGLIB-LOCATION>
</تاجليب>
</WEB-APP>
⑹ تم إعداد العلامة المخصصة باستخدام العلامات الجديدة ويمكن استخدامها على صفحة JSP. للقيام بذلك، ما عليك سوى الإعلان عن العلامة على الصفحة باستخدام توجيه taglib. تتم الإشارة إلى العلامة بواسطة معرف URI الفريد الخاص بها ويتم تعيين بادئة مساحة الاسم. يمكن أن تكون البادئة عشوائية طالما أنها لا تتعارض مع مساحات الأسماء الأخرى.
استخدم علامات ترميز HTML على صفحة JSP:
<%@ taglib uri="HTMLEncode" prefix="Examples" %>
<قبل>
<?XML:NAMESPACE PREFIX = أمثلة /><أمثلة:HTMLEncode>
<مرحبا، عينة بسيطة>
</أمثلة:HTMLEncode>
</بري>
نموذج لإخراج الكود
<مرحبا، عينة بسيطة>
الذي يعرض على النحو التالي:
<مرحبًا، عينة بسيطة>
باستخدام هذه العلامة، قمت بتشفير كافة أكواد الصفحة. الشيء المثير للاهتمام هو أن جميع العلامات المخصصة يتم التعامل معها على الخادم. وهذا يعني أنك لن ترى علامات مخصصة على صفحة الإخراج.
ليس من الصعب إنشاء ملصق. الجزء الأصعب هو تعلم كل خصوصيات وعموميات معالجة الملصقات. هذه ميزة قوية للغاية، وقد تطرقنا فقط إلى الأساسيات. نظرًا لأن هذه العملية تتطلب عدة خطوات، فسيتم الخلط بين مبرمجي JSP الجدد عند إنشاء العلامات.
كيفية استخدام JSP لتطوير تطبيقات DOM؟
DOM هو اختصار لـ Document Object Model، وهو نموذج كائن المستند. ينظم XML البيانات في شجرة، لذا فإن DOM هو وصف كائن لهذه الشجرة. في مصطلحات الشخص العادي، يتم بناء نموذج شجرة بشكل منطقي لمستند XML عن طريق تحليل مستند XML، وعقد الشجرة هي كائنات. يمكننا الوصول إلى محتوى مستندات XML عن طريق الوصول إلى هذه الكائنات.
دعونا نلقي نظرة على مثال بسيط أدناه لمعرفة كيفية تشغيل مستند XML في DOM. هذا مستند XML والكائن الذي نريد العمل عليه:
<?xml version="1.0" encoding="UTF-8"?>
<الرسائل>
<message>وداعا للتسلسل، ومرحبا جافا!</message>
</messages>
بعد ذلك، نحتاج إلى تحليل محتوى هذا المستند إلى كائنات Java ليستخدمها البرنامج. باستخدام JAXP، يمكننا القيام بذلك ببضعة أسطر من التعليمات البرمجية. أولاً، نحتاج إلى إنشاء مصنع محلل لاستخدام هذا المصنع للحصول على كائن محلل محدد:
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
الغرض من استخدام DocumentBuilderFacotry هنا هو إنشاء برنامج مستقل عن المحلل اللغوي المحدد. عندما يتم استدعاء الطريقة الثابتة newInstance() لفئة DocumentBuilderFactory، فإنها تحدد المحلل اللغوي الذي سيتم استخدامه بناءً على متغير النظام. ولأن جميع المحللين يتبعون الواجهة المحددة بواسطة JAXP، فإن الكود هو نفسه بغض النظر عن المحلل اللغوي الذي يتم استخدامه. لذلك عند التبديل بين المحللين المختلفين، ما عليك سوى تغيير قيم متغيرات النظام دون تغيير أي كود. هذه هي فائدة المصنع.
DocumentBuilder db = dbf.newDocumentBuilder();
بعد الحصول على كائن المصنع، استخدم الطريقة الثابتة newDocumentBuilder() للحصول على كائن DocumentBuilder، الذي يمثل محلل DOM محددًا. ولكن أي محلل هو، Microsoft أو IBM، ليس مهمًا للبرنامج.
بعد ذلك، يمكننا استخدام هذا المحلل لتحليل مستند XML:
المستند doc = db.parse("c:/xml/message.xml");
يقبل الأسلوب parse() الخاص بـ DocumentBuilder اسم مستند XML كمعلمة إدخال ويعيد كائن المستند يمثل كائن المستند هذا نموذجًا شجرة لمستند XML. جميع العمليات المستقبلية على مستندات XML ليس لها علاقة بالمحلل ويمكن تشغيلها مباشرة على كائن المستند هذا. يتم تحديد الطريقة المحددة لتشغيل المستند بواسطة DOM.
بدءًا من كائن المستند الذي تم الحصول عليه، يمكننا أن نبدأ رحلة DOM الخاصة بنا. باستخدام طريقة getElementsByTagName() لكائن المستند، يمكننا الحصول على كائن NodeList. يمثل كائن Node عنصر علامة في مستند XML، ويمثل كائن NodeList، كما ترون من اسمه، كائن Node List:
NodeList nl = doc.getElementsByTagName("message");
ما نحصل عليه من خلال مثل هذا البيان هو قائمة بكائنات العقدة المقابلة لجميع علامات <message> في مستند XML. بعد ذلك، يمكننا استخدام التابع item() الخاص بكائن NodeList للحصول على كل كائن Node في القائمة:
العقدة my_node = nl.item(0);
عند إنشاء كائن عقدة، يتم استخراج البيانات المخزنة في مستند XML وتغليفها في ملف Node. في هذا المثال، لاستخراج المحتوى داخل علامة الرسالة، نستخدم عادةً طريقة getNodeValue() لكائن Node:
String message = my_node.getFirstChild().getNodeValue();
يرجى ملاحظة أنه يتم استخدام طريقة getFirstChild() هنا أيضًا للحصول على أول كائن عقدة فرعي ضمن الرسالة. على الرغم من عدم وجود علامات فرعية أو سمات أخرى ضمن علامة الرسالة باستثناء النص، إلا أننا نصر على استخدام طريقة getFirseChild() هنا، والتي ترتبط بشكل أساسي بتعريف W3C لـ DOM. يعرّف W3C أيضًا جزء النص داخل العلامة على أنه عقدة، لذلك يجب علينا أولاً الحصول على العقدة التي تمثل النص قبل أن نتمكن من استخدام getNodeValue() للحصول على محتوى النص. الآن، بما أننا تمكنا من استخراج البيانات من ملف XML، فيمكننا استخدام هذه البيانات في المكان المناسب لبناء التطبيق.
مثال DOM
لنتحدث أولاً عما سيفعله هذا المثال، لقد قمنا بحفظ بعض عناوين URL في ملف يسمى link. تمت كتابة عنوان URL المضاف في ملف XML هذا. إنه بسيط جدًا، ولكنه عملي جدًا، ويكفي لتوضيح معظم استخدامات DOM.
البرنامج الأول يسمى xmldisplay.Java. وتتمثل وظيفته الرئيسية في قراءة محتويات كل عقدة في ملف XML، ثم تنسيق الإخراج على System.out. دعنا نلقي نظرة على هذا البرنامج:
import Javax.xml.parsers. *؛
import org.w3c.dom.*;
هذا هو تقديم الفئات الضرورية، لأنه يتم استخدام محلل XML المقدم من Sun هنا، لذلك يجب تقديم حزمة Java.xml.parsers، والتي تحتوي على محلل DOM وتحليل SAX. التنفيذ المحدد للجهاز. تحدد الحزمة org.w3c.dom واجهة DOM التي طورتها w3c.
DocumentBuilderFactory Factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
الوثيقة doc=builder.parse("links.xml");
doc.normalize();
بالإضافة إلى ما سبق، هناك أيضًا خدعة صغيرة. يمكن أن يؤدي استدعاء Normalize() على كائن Document إلى إزالة كائنات العقدة النصية غير الضرورية المعينة في شجرة DOM كفراغات في مستند XML كمحتوى منسق. وإلا فإن شجرة DOM التي تحصل عليها قد لا تكون كما تخيلتها. خاصة عند الإخراج، يكون هذا التطبيع () أكثر فائدة.
NodeList links =doc.getElementsByTagName("link");
كما ذكرنا للتو، سيتم أيضًا تعيين أحرف المسافات البيضاء في مستندات XML ككائنات في شجرة DOM. لذلك، فإن الاتصال المباشر بطريقة getChildNodes الخاصة بطريقة Node قد يواجه أحيانًا بعض المشكلات، وأحيانًا لا يتمكن من إرجاع كائن NodeList المتوقع. الحل هو استخدام getElementByTagName(String) للعنصر، وNodeLise الذي تم إرجاعه هو الكائن المتوقع. ثم يمكنك استخدام طريقة item() لاستخراج العنصر المطلوب.
for (int i=0;i<links.getLength();i++){
رابط العنصر = (العنصر) links.item(i);
System.out.print("المحتوى:");
System.out.println(link.getElementsByTagName("text").item(0).getFirstChild();
.getNodeValue());
...
يكمل مقتطف الكود أعلاه الإخراج المنسق لمحتوى مستند XML. طالما أنك تهتم ببعض التفاصيل، مثل استخدام طريقة getFirstChile() وطريقة getElementsByTagName()، فهي سهلة نسبيًا.
المحتوى التالي يدور حول إعادة كتابة شجرة DOM في مستند XML بعد تعديله. يُسمى هذا البرنامج xmlwrite.Java. في الإصدار JAXP 1.0، لا توجد فئات وأساليب مباشرة يمكنها التعامل مع كتابة مستندات XML، وتحتاج إلى استخدام بعض الفئات المساعدة في حزم أخرى. في الإصدار 1.1 من JAXP، تم تقديم دعم XSLT، ما يسمى بـ XSLT هو الحصول على بنية مستند جديدة بعد تحويل مستند XML (الترجمة). باستخدام هذه الوظيفة المضافة حديثًا، يمكننا بسهولة كتابة شجرة DOM التي تم إنشاؤها أو تعديلها حديثًا مرة أخرى إلى ملف XML ملف .xml:
استيراد Javax.xml.parsers.*;
import Javax.xml.transform.*;
import Javax.xml.transform.dom.DOMSource;
import Javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
يتم استخدام العديد من الفئات في حزمة Java.xml.transform المقدمة حديثًا للتعامل مع تحويلات XSLT.
نأمل أن نضيف عقدة ارتباط جديدة إلى ملف XML أعلاه، لذلك يجب علينا أولاً قراءة ملف links.xml، وإنشاء شجرة DOM، ثم تعديل شجرة DOM (إضافة عقد)، وأخيرًا إضافة كتابة DOM المعدلة مرة أخرى إلى ملف XML. ملف links.xml:
DocumentBuilderFactory Factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
الوثيقة doc=builder.parse("links.xml");
doc.normalize();
//---الحصول على المتغيرات----
String text="الصفحة الرئيسية لـ Hanzhong";
سلسلة URL = " www.hzliu.com "؛
مؤلف السلسلة = "هزليو ليو"؛
وصف السلسلة = "موقع من Hanzhong Liu، يمنحك الكثير من المفاجآت !!!"؛
من أجل رؤية النقاط الرئيسية بوضوح وتبسيط الإجراء، نقوم بترميز المحتوى المراد إضافته إلى كائن سلسلة الذاكرة فعليًا أثناء التشغيل، غالبًا ما نستخدم واجهة لاستخراج مدخلات المستخدم، أو استخراج المحتوى المطلوب من قاعدة البيانات عبر JDBC.
نصوص نصية، على سبيل المثال؛
Element link=doc.createElement("link");
أولا وقبل كل شيء، يجب أن يكون واضحا أنه بغض النظر عن نوع العقدة، سواء كان نوع النص أو نوع Attr أو نوع العنصر، يتم إنشاؤها جميعًا من خلال كائن المستند CreateXXX( ) الطريقة في (يمثل XXX النوع المحدد المراد إنشاؤه)، لذلك، نحتاج إلى إضافة عنصر رابط إلى مستند XML، قم أولاً بإنشاء كائن رابط:
Element linktext=doc.createElement("text");
texteg=doc.createTextNode(text);
linktext.appendChild(textseg);
link.appendChild(linktext);
...
قد تكون عملية إنشاء العقد موحدة بعض الشيء، ولكن ما يجب ملاحظته هو أن النص الموجود في العنصر (في DOM، تمثل هذه النصوص أيضًا عقدة، لذلك يجب أيضًا إنشاء العقد المقابلة لها). استخدم طريقة setNodeValue() مباشرة لكائن العنصر لتعيين محتوى هذه النصوص، وتحتاج إلى استخدام طريقة setNodeValue() لكائن النص الذي تم إنشاؤه لتعيين النص، بحيث يمكن تحديد العنصر الذي تم إنشاؤه ومحتوى النص الخاص به تمت إضافتها إلى شجرة DOM. ألقِ نظرة على الكود السابق وستفهم هذا بشكل أفضل:
doc.getDocumentElement().appendChild(link);
وأخيرًا، لا تنس إضافة العقدة التي تم إنشاؤها إلى شجرة DOM. تقوم طريقة getDocumentElement() لفئة المستند بإرجاع كائن العنصر الذي يمثل العقدة الجذرية للمستند. في مستند XML، يجب أن تكون العقدة الجذرية فريدة.
TransformerFactory tFactory =TransformerFactory.newInstance();
محول المحول = tFactory.newTransformer();
مصدر DOMSource = جديد DOMSource(doc);
نتيجة StreamResult = new StreamResult(new Java.io.File("links.xml"));
Transformer.transform(source, result);
ثم استخدم XSLT لإخراج شجرة DOM. يطبق TransformerFactory هنا أيضًا نمط المصنع، مما يجعل الكود المحدد مستقلاً عن المحول المحدد. طريقة التنفيذ هي نفس طريقة DocumentBuilderFactory، لذا لن أخوض في التفاصيل هنا. تقبل طريقة التحويل لفئة المحول معلمتين، مصدر البيانات المصدر والنتيجة المستهدفة للإخراج. يتم استخدام DOMSource وStreamResult هنا على التوالي، بحيث يمكن إخراج محتويات DOM إلى دفق إخراج. عندما يكون دفق الإخراج ملفًا، تتم كتابة محتويات DOM إلى الملف.
كيفية استخدام JSP لتطوير تطبيقات SAX؟
SAX هو اختصار لـ Simple API لـ XML، وهو ليس معيارًا رسميًا مقترحًا من قبل W3C، ويمكن القول أنه معيار واقعي "شعبي". في الواقع، هو نتاج نقاش مجتمعي. ومع ذلك، فإن SAX لا يقل استخدامًا في XML عن DOM، ويدعمه جميع موزعي XML تقريبًا.
بالمقارنة مع DOM، تعتبر SAX طريقة خفيفة الوزن. نحن نعلم أنه عند معالجة DOM، نحتاج إلى قراءة مستند XML بالكامل، ثم إنشاء شجرة DOM في الذاكرة وإنشاء كل كائن Node على شجرة DOM. عندما يكون المستند صغيرًا، فإن هذا لا يسبب أي مشاكل، ولكن بمجرد أن يصبح المستند أكبر، تصبح معالجة DOM تستغرق وقتًا طويلاً وشاقة. على وجه الخصوص، ستزداد أيضًا متطلبات الذاكرة الخاصة به بشكل كبير، بحيث لا يكون استخدام DOM في بعض التطبيقات فعالاً من حيث التكلفة (كما هو الحال في التطبيقات الصغيرة). في هذا الوقت، الحل البديل الأفضل هو SAX.
يختلف SAX تمامًا من الناحية النظرية عن DOM. بادئ ذي بدء، على عكس برنامج تشغيل مستند DOM، فهو يحركه الحدث، أي أنه لا يحتاج إلى قراءة المستند بأكمله، وعملية قراءة المستند هي أيضًا عملية تحليل SAX. يشير ما يسمى بالحدث إلى طريقة تشغيل البرنامج بناءً على آلية رد الاتصال. (إذا كنت واضحًا بشأن نموذج حدث الوكيل الجديد لـ Java، فسوف تفهم هذه الآلية بسهولة.) يقبل XMLReader مستند XML ويقوم بتحليله أثناء عملية قراءة مستند XML، أي عملية قراءة المستند. يتم تنفيذ عملية التحليل في نفس الوقت، وهو ما يختلف تمامًا عن DOM. قبل بدء التحليل، تحتاج إلى تسجيل ContentHandler في XMLReader، وهو ما يعادل مستمع الأحداث. يتم تعريف العديد من الأساليب في ContentHandler، مثل startDocument()، الذي يخصص ما يجب معالجته عندما تبدأ مواجهة المستند أثناء التحليل. عملية. عندما يقرأ XMLReader المحتوى المناسب، فإنه سيرمي الحدث المقابل، ويفوض قوة معالجة هذا الحدث إلى ContentHandler، ويستدعي الطريقة المقابلة له للرد.
قد يكون من الصعب بعض الشيء فهمه بشكل عام، لكن لا تقلق، ستساعدك الأمثلة التالية على فهم عملية تحليل SAX. ألقِ نظرة على ملف XML البسيط هذا:
<POEM>
<AUTHOR>أوغدن ناش</AUTHOR>
<TITLE>البراغيث</TITLE>
<LINE>آدم</LINE>
</POEM>
عندما يقرأ XMLReader علامة <POEM>، فإنه يستدعي أسلوب ContentHandler.startElement() ويمرر اسم العلامة POEM كمعلمة. يجب اتخاذ الإجراءات المقابلة في طريقة startElement() التي تنفذها للتعامل مع ما يجب القيام به عند ظهور <POEM>. يتم طرح كل حدث واحدًا تلو الآخر جنبًا إلى جنب مع عملية التحليل (أي عملية قراءة المستند)، ويتم استدعاء الأساليب المقابلة أيضًا بالتسلسل، وأخيرًا، عند اكتمال التحليل واستدعاء الأساليب، تتم معالجة المستند . هذا كل شيء. يسرد الجدول التالي الأساليب التي يتم استدعاؤها بشكل تسلسلي عند تحليل ملف XML أعلاه:
رد اتصال أسلوب المشروع الذي تمت مواجهته
{document start} startDocument()
<POEM> startElement(null،"POEM"،null,{Attributes})
الأحرف "n"("<POEM>n..."، 6، 1)
<AUTHOR> startElement(null"،AUTHOR"،null,{Attributes})
أحرف "أوغدن ناش"("<POEM>n..."، 15، 10)
</AUTHOR> endElement(null"،AUTHOR"،null)
"n" الأحرف("<POEM>n..."، 34، 1)
<TITLE> startElement(null,"TITLE",null,{Attributes})
أحرف "البراغيث"("<POEM>n..."، 42، 5)
</TITLE> endElement(null,"TITLE",null)
"n" الأحرف("<POEM>n..."، 55، 1)
<LINE> startElement(null,"LINE",null,{Attributes})
أحرف "آدم"("<POEM>n..."، 62، 4)
</LINE> endElement(null"،LINE"،null)
"n" الأحرف("<POEM>n..."، 67، 1)
</POEM> endElement(null,"POEM",null)
{End of document} endDocument()
ContentHandler هو في الواقع واجهة عند معالجة ملف XML محدد، تحتاج إلى إنشاء فئة تنفذ ContentHandler للتعامل مع أحداث معينة الوثيقة. دعونا نلقي نظرة على بعض الأساليب المحددة فيه:
الأحرف الفارغة (char[] ch, int start, int length): تُستخدم هذه الطريقة لمعالجة السلسلة المقروءة في ملف XML. المعلمة الخاصة بها هي مصفوفة أحرف ونقطة البداية لسلسلة القراءة في موضع البداية و length، يمكننا بسهولة استخدام مُنشئ فئة السلسلة للحصول على فئة السلسلة لهذه السلسلة: String charEncontered=new String(ch,start,length).
void startDocument(): عندما تواجه بداية المستند، قم باستدعاء هذه الطريقة للقيام ببعض أعمال المعالجة المسبقة.
void endDocument(): وفقًا للطريقة المذكورة أعلاه، عند انتهاء المستند، يتم استدعاء هذه الطريقة للقيام ببعض الأعمال اللاحقة.
void startElement(String namespaceURI, String localName, String qName, Attributes atts): سيتم تشغيل هذه الطريقة عند قراءة علامة البداية. مساحات الأسماء غير مدعومة في الإصدار SAX1.0، ولكن يتم توفير الدعم لمساحات الأسماء في الإصدار 2.0 الجديد. إن namespaceURI في المعلمة هنا هو مساحة الاسم، وlocalName هو اسم التسمية، وqName هي البادئة المعدلة للتسمية If لا يوجد عند استخدام مساحات الأسماء، لا تكون أي من المعلمتين فارغة. وatts هي قائمة السمات الموجودة في هذه العلامة. من خلال atts، يمكنك الحصول على جميع أسماء السمات والقيم المقابلة لها. تجدر الإشارة إلى أن إحدى الميزات المهمة لـ SAX هي معالجة التدفق. عند مواجهة علامة، لن يتم تسجيل العلامات التي تمت مواجهتها من قبل. بمعنى آخر، في طريقة startElement()، كل المعلومات التي تعرفها هي الاسم والسمات أما بالنسبة للبنية المتداخلة للعلامة، واسم العلامة العلوية، وما إذا كانت هناك سمات العناصر الفرعية، والمعلومات الأخرى المتعلقة بالبنية، فهي غير معروفة وتحتاج إلى برنامجك لإكمالها. وهذا يجعل SAX أقل ملاءمة للبرمجة من DOM.
void endElement(String namespaceURI, String localName, String qName): تتوافق هذه الطريقة مع الطريقة المذكورة أعلاه. يتم استدعاء هذه الطريقة عند مواجهة علامة نهاية.
مازلنا نستخدم مثال المستند الذي استخدمناه عند الحديث عن DOM، ولكن أولاً، دعونا نلقي نظرة على تطبيق أبسط ونأمل أن نحسب عدد المرات التي تظهر فيها كل علامة في ملف XML. هذا المثال بسيط للغاية، لكنه يكفي لتوضيح الأفكار الأساسية لبرمجة SAX. بالطبع، لا يزال بيان الاستيراد مستخدمًا في البداية:
import org.xml.sax.helpers.DefaultHandler;
import Javax.xml.parsers.*;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
استيراد Java.util.*;
import Java.io.*;
ثم نقوم بإنشاء فئة ترث من DefaultHandler، ويمكن وضع منطق البرنامج المحدد جانبًا في الوقت الحالي، وما يجب الانتباه إليه هو بنية البرنامج:
public class SAXCounter Extends DefaultHandler {.
علامات Hashtable الخاصة // يتم استخدام جدول التجزئة هذا لتسجيل عدد مرات ظهور العلامة
//العمل قبل معالجة المستند
public void startDocument() يلقي SAXException {
العلامات = new Hashtable();// تهيئة Hashtable
}
// معالجة كل سمة عنصر البداية
بداية الفراغ العام (String namespaceURI، String localName،
سلسلة اسم أولي، سمات atts)
يلقي SAXException
{
مفتاح السلسلة = الاسم المحلي؛
...
دعونا نرى ماذا يفعل هذا البرنامج. في الطريقة main()، الشيء الرئيسي الذي تفعله هو إنشاء محلل ثم تحليل المستند. في الواقع، عند إنشاء كائن SAXParser هنا، من أجل جعل كود البرنامج مستقلاً عن المحلل اللغوي المحدد، يتم استخدام نفس تقنية التصميم كما في DOM: إنشاء كائن SAXParser محدد من خلال فئة SAXParserFactory، بحيث عندما يكون التحليل مختلفًا كل ما يجب تغييره هو قيمة متغير البيئة، بينما يمكن أن يظل رمز البرنامج دون تغيير. هذه هي فكرة نمط FactoryMethod. لن أخوض في التفاصيل هنا، إذا كنت لا تزال لا تفهم، يمكنك الرجوع إلى الشرح في DOM أعلاه.
ولكن هناك شيء واحد يجب ملاحظته هنا، وهو العلاقة بين فئة SAXParser وفئة XMLReader. قد تكون مرتبكًا بعض الشيء. في الواقع، SAXParser عبارة عن فئة مجمعة لـ XMLReader في JAXP، وXMLReader هي واجهة محددة في SAX2.0 لتحليل المستندات. يمكنك أيضًا استدعاء الأسلوب parser() في SAXParser أو XMLReader لتحليل المستند، ويكون التأثير هو نفسه تمامًا. ومع ذلك، يقبل الأسلوب parser() في SAXParser المزيد من المعلمات ويمكنه تحليل مصادر بيانات مستندات XML المختلفة، لذا فهو أكثر ملاءمة للاستخدام من XMLReader.
يمس هذا المثال سطح SAX فقط، ولكن المثال التالي أكثر تقدمًا. الوظيفة التي نريد تنفيذها أدناه تم تنفيذها بالفعل في مثال DOM، وهي قراءة المحتوى من مستند XML وتنسيق الإخراج. على الرغم من أن منطق البرنامج لا يزال يبدو بسيطًا للغاية، إلا أن SAX ليس أفضل من DOM.
كما ذكرنا من قبل، عند مواجهة علامة البداية، في طريقة startElement()، لا يمكننا الحصول على موضع العلامة في مستند XML. هذه مشكلة كبيرة عند معالجة مستندات XML، لأن دلالات العلامات في XML يتم تحديدها جزئيًا حسب موقعها. وفي بعض البرامج التي تحتاج إلى التحقق من بنية المستند، يمثل هذا مشكلة أكبر. بالطبع، لا توجد مشكلة لا يمكن حلها، يمكننا استخدام المكدس لتسجيل بنية المستند.
خاصية المكدس هي ما يدخل أولاً يخرج أولاً. فكرتنا الحالية هي استخدام الدفع لإضافة اسم الملصق إلى المكدس في طريقة startElemnt()، وإخراجه في طريقة endElement(). نحن نعلم أنه بالنسبة إلى XML جيد التنظيم، تكون بنية التداخل الخاصة به مكتملة، حيث تتوافق كل علامة بداية دائمًا مع علامة النهاية، ولن يكون هناك اختلال في المحاذاة بين تداخل العلامات. لذلك، فإن كل استدعاء لطريقة startElement() سيتوافق حتمًا مع استدعاء لطريقة endElement()، لذلك يظهر الضغط والبوب أيضًا في أزواج، نحتاج فقط إلى تحليل بنية المكدس لمعرفة مكان التسمية الحالية بسهولة الموقف في بنية الوثيقة.
يمتد SaxReader من الطبقة العامة إلى الانفصال {
java.util.stack العلامات = new java.util.stack () ؛
...
على الرغم من أن تحليل المكدس لا يتم استخدامه هنا ، إلا أن تحليل المكدس هو مهمة سهلة للغاية يتم ترتيبها من أسفل إلى أعلى. سمات كل عنصر. في الواقع ، إذا قمنا بترتيب عناصر المكدس واحدًا تلو الآخر من الأسفل إلى الأعلى ، فسوف نحصل على مسار فريد من عقدة جذر XML إلى العقدة الحالية. .
حتى الآن ، قمنا بإتقان الأداة الرئيسية لبرمجة XML: DOM و SAX ، وأيضًا معرفة كيفية استخدامها في برنامج Java. برمجة DOM بسيطة نسبيًا ، لكنها بطيئة وتتناول الكثير من الذاكرة ، في حين أن برمجة S AX أكثر تعقيدًا ، ولكنها سريعة وتشغل ذاكرة أقل. لذلك ، يجب أن نختار استخدام طرق مختلفة وفقًا لبيئات مختلفة. يمكن حل معظم تطبيقات XML بشكل أساسي باستخدامها. تجدر الإشارة إلى أن DOM و SAX مستقلة في الواقع وليست فريدة من نوعها لـ Java.