تحفيز:
فكرت أولاً في إنشاء شجرة ثنائية لأنني كنت بحاجة إلى إنشاء مخطط هيكلي للشركة. كان الأسلوب السابق هو رسم صورة مباشرة باستخدام برامج الرسومات. يبدو رائعًا، لكنك تحتاج إلى رسم واحدة جديدة في كل مرة تحدث فيها تغييرات. ومن ناحية أخرى، فإن عرض وتخطيط الخطوط على صفحات الويب محدود للغاية. يعد التنضيد وتحديد المواقع بناءً على البيانات التي تم إنشاؤها ديناميكيًا أمرًا صعبًا للغاية، كما أن الجماليات ليست مرضية. بعد إجراء عدة محاولات، قررت استخدام XML+XSL لعمليات البيانات؛ واستخدام VML لتجميل الخطوط، واستخدام JAVASCRIPT لتحديد موضع الكائنات.
مادة:
يحتوي مخطط شجرة البنية لوحدة تخزين XML على ملفين:flow2.xml وflow2.xsl
تأثير:
تصفح هنا
يشرح:
فكرة الشجرة الثنائية (1)
<html xmlns:v="urn:schemas-microsoft-com:vml">
<النمط>
v:* { السلوك: url(#default#VML) }
</ستايل>
<v:معرف المجموعة = "group1" name = "group1" coordsize = "100,100">
…
</v:المجموعة>
هذه هي التنسيقات الأساسية لـ VML، لذا لن أشرحها بالتفصيل.
XML عبارة عن بنية شجرة عندما نقرأ كل البيانات، نحتاج إلى ذلك
يتم اجتياز شجرة بيانات XML. تعد العمليات العودية إحدى مزايا XSL.
قررت أيضًا استخدام XSL بعد استخدام طرق أخرى مختلفة لإجراء عمليات الاجتياز وفشلت.
<جذر التدفق>
<vcTitle>الشجرة الثنائية--مخطط البنية</vcTitle>
<Author>الطيران الشراعي</Author>
<Email>[email protected]</Email>
<عقدة التدفق>
<iProcess>1</iProcess>
<vcCourse>العقدة الأولى</vcCourse>
<iNextYes>
<عقدة التدفق>
<iProcess>2</iProcess>
<vcCourse>العقدة الثانية</vcCourse>
<iNextYes>…</iNextYes>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextYes>
<iNextNo>
<عقدة التدفق>
<iProcess>3</iProcess>
<vcCourse>العقدة الثالثة</vcCourse>
<iNextYes>…</iNextYes>
<iNextNo>…</iNextNo>
</FlowNode>
</iNextNo>
</FlowNode>
</فلو روت>
المنطق بسيط للغاية، هناك عقدتان فرعيتان (2، 3) تحت العقدة الحالية (1).
ما عليك سوى وضع العقدة 2 والعقدة 3 في أسفل اليسار وأسفل يمين العقدة 1.
أستخدم هنا اللون الأخضر والأحمر لخطوط التوصيل للعقدتين اليسرى واليمنى على التوالي لسهولة العرض.
لقد تحدثنا سابقًا عن الوظيفة العودية لـ XSL، لكي تتمكن من رؤية كل خطوة عرض تفصيلية بشكل أكثر وضوحًا، ما عليك سوى تقليد الكود التالي وإضافة بيان تنبيه.
<xsl:template match="FlowNode">
…
<لغة البرنامج النصي = "JavaScript1.2">
…
تنبيه ("عرض خطوة بخطوة")؛
…
</النص>
…
</xsl:قالب>
بعد مشاهدة الحركة البطيئة أعلاه، هل يمكنك فهم أفكاري؟
فكرة الشجرة الثنائية (2)
فكرتي بسيطة جداً:
(1) اقرأ بيانات العقدة الحالية وقم بإنشاء كائن جديد باستخدام VML.
قم بتعيين قيمة أولية للكائن (مثل الاسم والمعرف والنمط وما إلى ذلك)
(2) استخدم التحكم في البرنامج النصي لتحديد موضع الكائن الحالي (3) أضف أسهمًا وخطوطًا بين العقدة الحالية والعقدة الأصلية.
(4) استمر في العثور على العقد الفرعية للعقدة الحالية ثم قم بالتكرار حتى النهاية.
أي أنه تم اجتياز جميع العقد وتم إنشاء الشجرة.
<xsl:template match="FlowNode">
…
<xsl:تطبيق-القوالب />
…
</xsl:قالب>
<xsl:تطابق القالب = "iNextYes">
<xsl:apply-templates حدد = "./FlowNode" />
</xsl:template>
<xsl:template match="iNextNo">
<xsl:apply-templates حدد = "./FlowNode" />
</xsl:قالب>
تكتمل العملية العودية بأكملها من خلال الوحدات الثلاث المذكورة أعلاه (القوالب).
يستدعي القالب الأول القالبين التاليين عند مطابقة قالب كل عقدة فرعية في العقدة الحالية؛ ويستدعي القالبان الأخيران القالب الأول أثناء تنفيذ محدد، وهو ما يعادل وظيفة متكررة.
القواعد:
لمطابقة قوالب كل عقدة فرعية في العقدة الحالية بدورها، استخدم النموذج الأساسي للعنصر <xsl:apply-templates />.
بخلاف ذلك، يتم تحديد العقدة المطابقة بقيمة تعبير XPath في معلمة التحديد، مثل <xsl:apply-templates Select="./FlowNode" />
تتمثل وظائف (1) و (2) في إرجاع قيمة السلسلة للتعبير المقدم بواسطة معلمة التحديد.
شروط البحث الخاصة بهم هي نفسها، وبالتالي فإن القيم التي تم إرجاعها هي نفسها أيضًا.
إن الأمر فقط أن أشكال الكتابة الخاصة بهم تختلف اعتمادًا على المناسبات التي يتم استخدامها فيها.
(1) <xsl:قيمة التحديد = "./iProcess/text()" />
(2) {./iProcess/text()}
تم تعريف بعض المتغيرات هنا، ويعتمد موضع العقدة على هذه المتغيرات لاستدعاء صيغة الحساب.
root_left // الهامش الأيسر للجذر = العرض المخصص لجميع الأوراق (ص*10) + عرض جميع الأوراق (ص*50) + القيمة الأساسية للهامش الأيسر (10)
root_top // الهامش العلوي للجذر = القيمة الأساسية للهامش العلوي (10)
objOval // الكائن الحالي هو كائن
objOval_iProcess // قيمة الخطوة للكائن الحالي
objParentOval // العقدة الأصلية للكائن الحالي هي كائن
objParentOval_iProcess // قيمة الخطوة للعقدة الأصلية للكائن الحالي
objParent_name // اسم العقدة الأصلية للكائن الحالي
Leaf_left // عدد الأوراق اليسرى بين جميع العقد الفرعية للكائن الحالي
Leaf_right // عدد الأوراق اليمنى بين جميع العقد الفرعية للكائن الحالي
Leaf_sum // عدد الأوراق بين جميع العقد الفرعية للكائن الحالي
: يشير إلى العقدة الحالية التي لا تحتوي على عقد فرعية.
صيغة تحديد موضع العقدة:
(1) العقدة الحالية هي العقدة الجذرية
// موضع الجذر
SobjOval.style.left=parseInt(root_left);
SobjOval.style.top=parseInt(root_top);
// وظيفة وظيفة parseInt () هي أخذ القيمة الصحيحة، وإذا لم تكن كذلك، فستكون NAN
// وظيفة وظيفة isNaN () هي تحديد ما إذا كانت القيمة التي تم الحصول عليها بواسطة parseInt عددًا صحيحًا.
(2) العقدة الحالية هي العقدة الفرعية اليسرى للعقدة الأصلية
1) شروط الحكم هي: اسم العقدة الأصلية للكائن الحالي = 'iNextYes'
…
2) إذا كانت هناك ورقة فرعية صحيحة، فالصيغة هي:
يسار العقدة الحالية = يسار العقدة الأصلية - إجمالي عرض الورقة الفرعية اليمنى للعقدة الحالية - عرض العقدة الحالية
3) إذا لم يكن هناك ورقة فرعية يمينية، ولكن هناك ورقة فرعية يسرى ، الصيغة هي:
يسار العقدة الحالية = يسار العقدة الأصلية - إجمالي عرض الورقة الفرعية اليسرى للعقدة الحالية
4) إذا كانت العقدة الحالية نفسها عبارة عن ورقة، فإن الصيغة هي:
يسار العقدة الحالية = يسار العقدة الأم - عرض العقدة الحالية...
(3) العقدة الحالية هي العقدة الفرعية اليمنى للعقدة الأصلية
1) شروط الحكم هي: اسم العقدة الأصلية للكائن الحالي = 'iNextNo'
…
2) إذا كانت هناك ورقة فرعية يسرى، فالصيغة هي:
يسار العقدة الحالية = يسار العقدة الأصلية + إجمالي عرض الورقة الفرعية اليسرى للعقدة الحالية + عرض العقدة الحالية
3) إذا لم يكن هناك ورقة فرعية يسرى، ولكن هناك ورقة فرعية يمينية ، الصيغة هي:
يسار العقدة الحالية = يسار العقدة الأصلية + إجمالي عرض الورقة الفرعية اليمنى للعقدة الحالية
4) إذا كانت العقدة الحالية نفسها عبارة عن ورقة، فإن الصيغة هي:
يسار العقدة الحالية = يسار العقدة الأصلية + عرض العقدة الحالية...
تحصل الصيغتان (2) و (3) على يسار العقدة الحالية، ونحتاج أيضًا إلى الحصول على الجزء العلوي من العقدة الحالية.
صيغة بسيطة جدًا: أعلى العقدة الحالية = أعلى العقدة الأصلية + الإزاحة (80)
فكرة الشجرة الثنائية (3)
أفكار لتحديد المواقع لربط الخطوط:
(1) ابحث عن موضع العقدة الحالية والعقدة الأصلية (2) حدد ما إذا كانت العقدة الحالية هي العقدة الفرعية اليسرى أو العقدة الفرعية اليمنى للعقدة الأصلية (3) ارسم خطًا
يتم تعريف بعض المتغيرات هنا.
objOval // العقدة الحالية هي كائن
objParentOval // العقدة الأصلية للكائن الحالي هي كائن
objLine // السطر الحالي هو كائن
صيغة تحديد موضع الخط:
من = "x1، y1" إلى = "x2، y2" هي طريقة تحديد موضع الخطوط في VML.
العقدة الحالية هي العقدة الفرعية اليسرى للعقدة الأصلية، والصيغة هي:
من = يسار العقدة الأصلية + الإزاحة (15)، أعلى العقدة الأصلية + الإزاحة (32)
إلى = اليسار + الإزاحة (30) للعقدة الأصلية، والأعلى - الإزاحة (2) للعقدة الأصلية
.
من = يسار العقدة الأصلية + الإزاحة (35)، أعلى العقدة الأصلية + الإزاحة (32)
إلى = يسار العقدة الأصلية + الإزاحة (20)، أعلى العقدة الأصلية - الإزاحة (2)
هذا كل ما يمكنني التفكير فيه.
سيكون الأمر أسهل بكثير إذا قمنا للتو بإعداد مخطط هيكلي للشركة.
ما يلي هو فكرة Cy Young، وأنا أتعمق قليلًا في أساسها.
قم أولاً بحساب عدد العقد في المستوى السفلي للحصول على العرض،
يجب بعد ذلك حساب موضع العقدة العليا بناءً على انتمائها، بشكل متكرر.
يجب فرز العقد في كل مستوى حسب انتمائها. أولاً، قم بتعيين "القيمة الأساسية" = يجب إزاحة العقدة إلى اليمين. القيمة اليسرى لكل عقدة تحتوي على عقد فرعية تساوي نصف عرض العقدة يمتلك بالإضافة إلى القيمة الأساسية.
بوستسكريبت:
لسبب ما، كان الإنترنت سيئا في الآونة الأخيرة. قضاء المزيد من الوقت دون الاتصال بالإنترنت مقارنة بالإنترنت.
لذلك، لم يتم تبسيط الكود، في الواقع، لا تزال هناك العديد من الوظائف التي تحتاج إلى تحسين، مثل:
تحتاج إلى إضافة قائمة النقر بزر الماوس الأيمن، تحتوي قائمة النقر بزر الماوس الأيمن على القدرة على إنشاء عقد جديدة، وتعديل أسماء العقد، وتغيير الارتباطات، وما إلى ذلك. يمكنك النقر بزر الماوس الأيمن على كل عقدة لفتح قائمة النقر بزر الماوس الأيمن لهذه العقدة. .
يشرح:
1)flow2.xml هو ملف بيانات، وأعتقد أن الجميع لن يواجهوا أي مشكلة.
2)flow2.xsl هو ملف بتنسيق، وهناك العديد من الأشياء التي يجب الانتباه إليها.
(1) في البرنامج النصي:
(1) <xsl:value-of Select="./iProcess/text()" />;
(2) {./iProcess/text()}
تتمثل وظائف (1) و (2) في إرجاع قيمة السلسلة للتعبير المقدم بواسطة معلمة التحديد.
شروط البحث الخاصة بهم هي نفسها، وبالتالي فإن القيم التي تم إرجاعها هي نفسها أيضًا.
إن الأمر فقط أن أشكال الكتابة الخاصة بهم تختلف اعتمادًا على المناسبات التي يتم استخدامها فيها.
<xsl:apply-templates حدد = "team" order-by = "blue_ID"/>
على سبيل المثال، نريد إنشاء الكود التالي
<div name="parameter value">المحتوى</div>
نفترض أن الاسم هو "اسم" وأن قيمة المعلمة هي قيمة كتاب العقدة الفرعية ضمن العقدة الحالية في بيانات XML.
الطريقة الأولى لكتابتها هي إضافة اسم السمة أولاً ثم قيمة المعلمة.
<ديف>
<xsl:اسم السمة = "الاسم">
<xsl:value-of تحديد = "./book/text()"/> </xsl:attribute>
محتوى
</div>
الطريقة الثانية للكتابة هي إضافة اسم السمة وقيمة المعلمة مباشرة
<div name="{./book/text()}">المحتوى</div>
للاستخدام المحدد، يمكنك رؤية الأمثلة في الكود الذي كتبته.
XSL موجود في المعيار الرسمي xmlns:xsl=" http://www.w3.org/1999/XSL/Transform "
<xsl:value-of Select="./book/text()"/>
الوظيفة هي: فقط اكتب قيمة النص الخاصة به، و
<xsl:قيمة التحديد='./book'/>
يعرض قيمته النصية ومحتويات جميع العقد الفرعية الخاصة به.
يمكنك تجربتها وإخراج واحدة تحتوي على عقد فرعية وأخرى بدون عقد فرعية لمعرفة ما إذا كانت النتائج المعروضة هي نفسها.
(2) ملاحظة:
IE5 لا يدعم <tag att="{xpath}">
تريد استخدامها
<tag><xsl:attribute name="att"><xsl:value-of تحديد="xpath"></xsl:attribute>
يجب استخدام مساحة الاسم
xmlns:xsl=" http://www.w3.org/TR/WD-xsl "
<?xml version="1.0" encoding="gb2312" ?>
شيء آخر:
نادرًا ما تتم إضافة التشفير = "gb2312" إلى الكود الموضح في معظم كتب XML المدرسية.
لذلك، عندما نستخدم اللغة الصينية في XML، سيتم الإبلاغ عن خطأ والسبب هو عدم كتابة هذا الإعلان.
حاشية:
ما أتحدث عنه هنا هو طريقة التفكير. إذا قمت برسم تشبيه، فمن الطبيعي أن يكون مفيدًا.