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

ASP.NET + XML + XSLT

بدأه Robatic في 17 فبراير 2010 · 9 رد · 2,940 مشاهدة · في ASP.NET
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

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

في الآونة الأخيرة كلنا سمعنا عن الـ XML وأنها قامت بكسر الحواجز بين التطبيقات المختلفة وأنها جعلت تناقل البيانات ومشاركتها عملية بسيطة وليست كابوسا كما كانت. أيضا قامت شركة Microsoft بتبني وإعتماد هذه التكنولوجيا حيث أن ملفات الـ Office 12/Office 2007 هي حرفيا عبارة عن XML حيث أن هذا الإهتمام أو الـ Standardize أدى إلى ما يعرف بي Office Open XML file format. لن أطيل الحديث عن الـ Office Open XML حيث أنه خارج نطاق موضوعنا.

تمهيد :

لقرائة ملف XML بلغة CSharp يمكنك إستخدام المكتبة System.Xml حيث أنها تحوي XmlReader و XmlTextReader حيث أن كل منهما يقومان بقراءة ملف XML وبشكل تقدمي (Forward-Only). المقصود بشكل تقدمي هنا أي أن القراءة بإتجاه واحد مثلها مثل الـ SqlDataReader أو OleDbDataReader بمعنى أنه عندما تطلب القراءة بإستخدام الدالة Read سيتقدم المؤشر إلى العنصر التالي. دعونا نرى كيف تحدث هذه العملية:

لنفرض أن لدينا ملف الـ XML التالي :

<?xml version="1.0" encoding="utf-8"?>
     <MultiStockOrder>
       <StockOrderMultiple>
         <StockOrder>
           <Symbol>MSFT</Symbol>
           <Quantity>100</Quantity>
           <OrderTime>2005-10-04</OrderTime>
         </StockOrder>
         <StockOrder> 
           <Symbol>INTC</Symbol>
           <Quantity>110</Quantity>
           <OrderTime>2005-10-04</OrderTime>
         </StockOrder>
         <StockOrder>
           <Symbol>RTRSY</Symbol>
           <Quantity>200</Quantity>
           <OrderTime>2005-10-04</OrderTime>
         </StockOrder>
        </StockOrderMultiple>
     </MultiStockOrder>

وهدفنا هنا هو طباعة قيمة محتوى العنصر Symbol ، سيكون الكود كالتالي

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;

namespace XmlProject
{
	class Program
        {
        	static void Main(string[] args)
		{
        	         try
                	 {
			    // The following are self explanatory settings

	                    XmlReaderSettings settings = new XmlReaderSettings();
        	            settings.IgnoreWhitespace = true;
                	    settings.IgnoreComments = true;
	                    settings.CheckCharacters = true;

	                    FileStream myStockOrders = new
        	               FileStream("your xml file path", FileMode.Open);

	                    XmlReader xr = XmlReader.Create(myStockOrders, settings);

	                    while (xr.Read())
        	            {
                	        if (xr.NodeType == XmlNodeType.Element &&
                        	    "Symbol" == xr.LocalName)
	                        {
        	                    Console.WriteLine(xr.Name + " " +
                	              xr.ReadElementContentAsString());
                        	} 
	                    }

                	    xr.Close();

	                    Console.WriteLine("Done");
                	    Console.ReadLine();
	                 }
        	         catch (System.Exception ex)
                	 {
	                    Console.Error.WriteLine(ex.ToString());
        	            Console.ReadLine();
	                 }
        	}
	}
}

السؤال الذي يطرح نفسه هو : ما الفائدة من قرائتي لملف XML بطريقة تقدمية فقط ؟

أفرض أنه طلب منك أن تقوم بكتابة كود يتعامل مع ملف XML بطريقة معينه حيث أن القراءة التقدمية تكون عقيمة، بمعنى آخر كيف يتم التنقل بأريحية (Navigation) وسط ملف الـ XML. هنا سنتطرق لمصطلح قد يكون على البعض جديد وهو الـ XPath. لتبسيط الـ XPath تخيل أنها عبارة عن ملفات نظام windows في الـ command-prompt ولكن بدل أن تستخدم \ قم بإستخدام /، بمعنى آخر تخيل أنك في الـ Shell-command في نظام تشغيل Linux. لتبسيط العملية أكثر، إذا أردنا الحصول على نفس النتيجة في المثال السابق نقوم بكتابة التعبير (expression) التالي:

MultiStockOrder/StockOrderMultiple/StockOrder/Symbol

أيضا يمكنك إستخدام كلا من "." و ".."، حيث أن الأولى تشير للعنصر الحالي والثانية تشير إلى العنصر الأب على التوالي، تماما كنظام الملفات في نظام تشغيل Linux. وفي حالة أن العنصر كان يحوي attribute وطلب منك إستخراج قيمته كل ما عليك فعله هو الوصول إلى ذلك العنصر ثم إستخدام @ كما هو موضح في المثال التالي:

elemtn1/element2/...../required-element/@attribute-name

على نفس المثال السابق دعونا نرى كيفية إستخدام XPath في لغة CSharp، الكود :

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.IO;

namespace XmlProject
{
	class Program
	{ 
		static void Main(string[] args)
		{
			try
			{
				FileStream myStockOrders = new
				FileStream("your xml file path", FileMode.Open);

				XPathDocument myDocument = new XPathDocument(myStockOrders);
				XPathNavigator docNavigation = myDocument.CreateNavigator();

				foreach(XPathNavigator node in
					docNavigation.Select("//MultiStockOrder/StockOrderMultiple/StockOrder/Symbol"))
				{
					Console.WriteLine(node.Value.ToString());
				}

				Console.WriteLine("Done");
				Console.ReadLine();
			}
			catch (System.Exception ex)
			{
				Console.Error.WriteLine(ex.ToString());
				Console.ReadLine();
			}
		}
	}
}

إمكانيات الـ XPath لا تقتصر فقط على إستخراج البيانات من ملف XML بل تحتوي أيضا على أدوات منطقية وما إلى ذلك وللمزيد من المعلومات أتبع الرابط التالي

http://msdn.microsoft.com/en-us/library/ms256086.aspx

ASP.NET & XML

الموضوع أبسط مما يبدو عليه بعكس االأمثلة السابقة، بل يمكنك قراءة وعرض ملفات XML من غير أن تقوم بكتابة سطر واحد في الـ Code Behind. حتى تتضح الفكرة أكثر سنقوم بالتدرج بدءا بعرض ملف XML بإستخدام XmlDataSource و GridView (ملاحظة: نفس الفكرة تنطبق أيضا على كل من DataList, ListView, DetailsView .... etc) وإنتهائا بإستخدام ملف XSLT و asp:Xml control . في جميع الأمثلة التالية سنقوم بإستخدام ملف الـ XML التالي والذي سيكون تحت اسم games.xml، الملف :

<?xml version="1.0" encoding="utf-8" ?>
<games>
  <game platform="pc">
    <name>Dragon Age: Origions</name>
    <genre>Computer Role-Playing</genre>
    <releasedate>11/3/2009</releasedate>
  </game>
  <game platform="pc">
    <name>Mass Effect 2</name>
    <genre>Action Role-Playing</genre>
    <releasedate>1/26/2010</releasedate>
  </game>
  <game platform="pc">
    <name>Left 4 Dead 2</name>
    <genre>Sci-Fi First-Person Shooter</genre>
    <releasedate>11/17/2009</releasedate>
  </game>
  <game platform="xbox">
    <name>Aliens vs. Predator</name>
    <genre>Action</genre>
    <releasedate>2/16/2010</releasedate>
  </game>
  <game platform="xbox">
    <name>Dynasty Warriors: Strikeforce</name>
    <genre>Action</genre>
    <releasedate>2/16/2010</releasedate>
  </game>
  <game platform="xbox">
    <name>Tropico 3</name>
    <genre>Other Strategy Games</genre>
    <releasedate>2/16/2010</releasedate>
  </game>
  <game platform="ps3">
    <name>Braid</name>
    <genre>2D Platform</genre>
    <releasedate>11/12/2009</releasedate>
  </game>
  <game platform="ps3">
    <name>Uncharted 2: Among Thieves</name>
    <genre>Modern Action Adventure</genre>
    <releasedate>10/13/2009</releasedate>
  </game>
  <game platform="ps3">
    <name>Assassin's Creed II</name>
    <genre>Historic Action Adventure</genre>
    <releasedate>11/17/2009</releasedate>
  </game>
</games>

أولا : XmlDataSource

مثلة مثل الـ SqlDataSource ولكن بدل من أن تقوم بتحديد الـ ConnectionString و الـ SelectCommand قم بتحديد كل من DataFile و XPath حيث أن الأول هو عبارة عن عنوان URL ملف الـ XML المراد عرضه والثاني هو عبارة عن تعبر expression كما سبق ذكره. سيكون الكود في الـ design كالتالي :

<asp:GridView ID="gamesGridView" runat="server" AutoGenerateColumns="false" DataSourceID="gamesDataSource"
            Width="700px" CellPadding="5">
            <HeaderStyle BackColor="#a3a3f0" />
            <Columns>
                <asp:TemplateField HeaderText="Title">
                    <ItemTemplate>
                        <%# XPath("name") %>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Platform">
                    <ItemTemplate>
                        <%# XPath("@platform") %>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Genre">
                    <ItemTemplate>
                        <%# XPath("genre") %>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Release Date">
                    <ItemTemplate>
                        <%# XPath("releasedate") %>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>
        <asp:XmlDataSource ID="gamesDataSource" runat="server" DataFile="~/games.xml" XPath="/games/game" />

ثانيا : XSLT & asp:Xml Control

الـ XSLT هي إختصار لـ eXtensible Stylesheet Language Transformations وهي عبارة عن لغة لنقل ملف XML من شكلة الحالي إلى شكل آخر، قد يكون HTML أو Text أو ملف XML ولكن بشكل آخر غير الملف الأصلي. في بداية الأمر عندما تقوم بالتوغل في الـ XSLT ستلاحظ أنها غريبة جدا ولكن صدقوني عندما تتعودوا عليها وتشاهدوا مثالا أو أكثر ستلاحظ أنها أقرب إلى SQL Transit. ببساطة الـ XSLT يتم من خلالها إنشاء template أو أكثر ووفقا لـ XPath expression يتم تطبيق الـ template على مجموعة العناصر الناتجة من الـ XPath expression. قبل كل شيء دعونا نرى ملف XSLT في أبسط صورة :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:template match="/">

	<!--
		YOUR TEMPLATE GOES HERE
	-->

  </xsl:template>
</xsl:stylesheet>

لاحظ العنصر xsl:template وهو المسؤول عن إنشاء قالب بالشكل الذي تريده وأيضا لاحظ أنه يحوي على attribute بإسم match حيث أنه يأخذ قيمة XPath expression وفي حالتنا هنا القيمة هي / وهي تدل على محتوى ملف الـ XML كاملا. دعونا نقوم بالتعديل على ملف الـ XSLT السابق وتغييرة إلى :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:template match="/">

	<h1>Hellow World!</h1>

  </xsl:template>
</xsl:stylesheet>

التعديل الأخير سيقوم بتوليد الـ HTML التالي <h1>Hellow World!</h1> لمرة واحدة وذلك لأن أي ملف XML يحوي على عنصر جذر واحد فقط (Root element). ولكي تقوم بعمل loop للعناصر الموجودة تحت العنصر الجذر يمكنك إستخدام العنصر

<xsl:for-each select ="an XPath expression"></xsl:for-each>

حيث أن الـ attribute الذي يحمل الإسم select هو عبارة عن XPath expression، فلنفرض على ضوء ملف الـ XML والذي يحمل الإسم games.xml أننا قمنا بتعديل ملف الـ XSLT إلى التالي :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:template match="/">

    	<xsl:for-each select="games/game">

		<h1>Hellow World!</h1>

	</xsl:for-each>

  </xsl:template>
</xsl:stylesheet>

ماذا تتوقع أن تكون النتيجة النهائية ؟ ستكون كتابة الجملة Hello Wordl! تسعة مرات، وذلك بسبب الـ XPath expression الموجود في العنصر xsl:for-each حيث أن عدد العناصر المرجعة من هذا التعبير هو 9 وفقا للملف games.xml. ولإستخلاص قيمة عنصر من ملف XML عن طريق ملف XSLT قم بإستخدام العنصر xsl:value-of والتي تحتوي على الـ attribute الذي يحمل اسم select وهو أيضا عبارة عن XPath expression.

دعونا نرى كيف نعرض محتوى ملف XML عن طريق asp:Xml و ملف XSLT وصدقوني أنه بعد ما يتم إنشاء ملف الـ XSLT كل ما يلزمنا هو سطر واحد فقط. سيكون ملف الـ XSLT بإسم games_xslt.xslt وهو كالتالي :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:template match="/">

    <xsl:for-each select ="games/game">
      <p style="padding: 5px;">
        <h4 style="color: #a3a3f0">
          <xsl:value-of select="name"/>
        </h4>
        <font style="font-size: 7pt; font-family: Tahoma; font-style:italic; font-wieght: bold;">
          [Genre: <xsl:value-of select="genre"/>] [Release Date: <xsl:value-of select="releasedate" />]
        </font>
      </p>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

وفي الـ Design في صفحة الـ ASP.NET سيكون الكود كالتالي :

<asp:Xml ID="gamesXml" runat="server" DocumentSource="~/games.xml" TransformSource="~/games_xslt.xslt" />

لاحظ أننا قمنا بتحديد ملف الـ XML عن طريق الخاصية DocumentSource والتي هي عبارة عن رابط وقمنا بتحديد ملف الـ XSLT عن طريق الخاصية TransformSource. ماذا لو أردنا ترتيب نتائج ملف الـ XML أبجديا على حسب اسم اللعبه ؟ يمكنك إستخدام العنصر xsl:sort والذي يحوي على attribute باسم select وهو أيضا عبارة عن XPath expression، سيكون ملف الـ XSLT كالتالي :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:template match="/">

    <xsl:for-each select ="games/game">

      <xsl:sort select="name"/>

      <p style="padding: 5px;">
        <h4 style="color: #a3a3f0">
          <xsl:value-of select="name"/>
        </h4>
        <font style="font-size: 7pt; font-family: Tahoma; font-style:italic; font-wieght: bold;">
          [Genre: <xsl:value-of select="genre"/>] [Release Date: <xsl:value-of select="releasedate" />]
        </font>
      </p>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

ماذا لو أردنا عرض الألعب التي تنتدرج تحت platform pc فقط، يمكنك إستخدام العنصر

<xsl:if test="an XPath expression"></xsl:if>

حيث أن test أيضا عبارة عن XPath expression، سيكون ملف الـ XSLT كالتالي :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:template match="/">

    <xsl:for-each select ="games/game">

      <xsl:if test="@platform='pc'">

        <p style="padding: 5px;">
          <h4 style="color: #a3a3f0">
            <xsl:value-of select="name"/>
          </h4>
          <font style="font-size: 7pt; font-family: Tahoma; font-style:italic; font-wieght: bold;">
            [Genre: <xsl:value-of select="genre"/>] [Release Date: <xsl:value-of select="releasedate" />]
          </font>
        </p>

      </xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

وأخيرا وليس آخرا هناك أيضا عنصر فعال وهو xsl:choose والذي يحوي أيضا عنصرين هما xsl:when و xsl:otehrwise ويمكنك أن تتخيل أنهم مثل If-Else ويمكنك إستخدامهم كالتالي

<xsl:choose>

	<xsl:when test="an XPath expression">

		<!-- Your template goes here -->	

        </xsl:when>

	<xsl:when test="an XPath expression">

		<!-- Your template goes here -->	

	</xsl:when>

	<xsl:when test="an XPath expression">

		<!-- Your template goes here -->	

	</xsl:when>

	.
	.
	.
	.

	<xsl:otherwise>

		<!-- Your template goes here -->	

	</xsl:otherwise>

</xsl:choose>

والآن دعونا نقوم بالتالي وهو إستخدما العنصر xsl:choose بحيث يتم فحص الـ platform الخاص باللعبه حيث يتم عرض صورة تدل على كل نوع فمثلا لو كانت القيمة pc يتم عرض صورة شعار windows وهكذا، سيكون ملف الـ XSLT كالتالي :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:template match="/">

    <xsl:for-each select ="games/game">

      <p style="padding: 5px; filter: progid : DXImageTransform.Microsoft.Alpha(opacity=0);">
        <h4 style="color: #a3a3f0;">
          <xsl:value-of select="name"/>

          <xsl:choose>

            <xsl:when test="@platform = 'pc'">
              <img src="images/win.png" alt="Windows" style="vertical-align: middle; margin-left: 20px;" />
            </xsl:when>

            <xsl:when test="@platform = 'xbox'">
              <img src="images/xbox.png" alt="XBox 360" style="vertical-align: middle; margin-left: 20px;" />
            </xsl:when>

            <xsl:otherwise>
              <img src="images/ps3.png" alt="Play Station 3" style="vertical-align: middle; margin-left: 20px;" />
            </xsl:otherwise>

          </xsl:choose>

        </h4>
        <font style="font-size: 7pt; font-family: Tahoma; font-style:italic; font-wieght: bold;">
          [Genre: <xsl:value-of select="genre"/>] [Release Date: <xsl:value-of select="releasedate" />]
        </font>
      </p>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

الخلاصة :

يمكنك إعتبار ملف الـ XSLT عبارة عن ملف CSS ولكن ليس لصفحة إلكترونبة بل لملف XML حيث أنه يمكنك تغيير ملف الـ XSLT ومن ثم رفعه لموقعك وذلك لغرض تغيير طريقة عرض البيانات دون الحاجة لكتابة كود ومن ثم compile ومن ثم الرفع. وأيضا أحد الفوائد الممكنه هو حل مشلكة السيناريو التالي: تخيل انك تعمل لشركة لديها نظامين مختلفين الأول بلغة java وقاعدة البيانات oracel والآخر بلغة CSharp وقاعدة البيانات MS SQL وكان البرنامج الأول يصدر ملفات XML بشكل معين والآخر يمكن أن يقراء ملفات XML ولكن بشكل لا يتناسب مع الملفات الصادرة من النظام الأول، وأفرض أن الكود (المصدر) غير موجود، كيف يمكنك أن تكامل (integrate) بينهم ؟ بإستخدام الـ XSLT يمكنك بناء قالب يتنباسب مع النظام الثاني بحيث يتم توليد القالب من محتوى الـ XML الصادر من النظام الأول. وذلك عن طريق العنصر xsl:apply-template، وللأسف الشديد أنا ليست لدي أدنى فكرة عنه ولكن أوعدكم أن أقوم بالبحث وكتابة موضوع بخصوصة.

ملاحظة : عندما تستخدم العنصر xsl:if وتريد أن تفحص قيمة ما إذا كانت أكبر من عدد معين، لن يكون هناك مشكلة ولكن لو أستخدمة العلامة أصغر من وأردت أن تفحص قيمة ما إذا كانت أصغر من عدد معين فهذا سيؤدي إلى خطأ أجهل سببه. لو كان المطلوب منك هو فحص قيمة ما إذا كانت أصغر من عدد معين فقم بإستخدام العنصر xsl:choose.

في المرفقات ستجدون مشروع كامل لكل الحالات التي م عرضها هنا المتعلقه فقط بـ ASP.NET, XML & XSLT.

أتمنى للجميع التوفيق

XMLTest.zip

3
#2

مواضيعك حول ال XML Technologies قيمة و مفيدة لنا جزاك الله خيراً

Technical Lead Developer

My LinkedIn Profile

اللهم قنى شر الجهل و الجهلاء

( اقْتَرَبَ لِلنَّاسِ حِسَابُهُمْ وَهُمْ فِي غَفْلَةٍ مَّعْرِضُونَ ) {الأنبياء:1}

#3

جزاك الله كل خير

ASP.NET Team Leader

moh_kin_mah@hotmail.com

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

لو أعجبك أي من مشاركاتي ... برجاء قم بتقييم المشاركة عبر الأزرار الموجودة أسفل يسار كل مشاركة

#4

جزاك الله خيرا

#5

شكرا جزيلا للأخ Robatic على الشرح الجميل المبسط الموضوع مهم للغاية و أرجو منك مناقشة الموضوع بشكل أوسع :) :happy: :happy:

#6

مشكور أخي الفاضل

#7

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

أولا : أحب أن أشكر كل من أخواني الكرام الأستاذ / طارق إبراهيم، والأستاذ / moh_kin، والأستاذ / mobarmijt، والأستاذ / JSWE على مرورهم الكريم.

ثانيا : كما وعدت سأقوم بالتطرق لكيفية إستخدام العنصر xsl:apply-templates في هذا الرد

xsl:apply-templates

يقوم هذا العنصر بتطبيق xsl:template على العنصر الحالي أوعلى جميع الـ children للعنصر الحالي، وهذه هي طريقة إستخدام العنصر xsl:apply-templates

<xsl:apply-templates select="XPath expression" />

ملاحظة: في حالة تحديد الـ select attribute سيتم تطبيق القالب على الـ Children فقط للعنصر الناتج من الـ XPath expression

وللتذكير فقط هذا هو ملف الـ XML الذي سنتطبق عليه المثال :

<?xml version="1.0" encoding="utf-8" ?>
<games>
  <game platform="pc">
    <name>Dragon Age: Origions</name>
    <genre>Computer Role-Playing</genre>
    <releasedate>11/3/2009</releasedate>
  </game>
  <game platform="pc">
    <name>Mass Effect 2</name>
    <genre>Action Role-Playing</genre>
    <releasedate>1/26/2010</releasedate>
  </game>
  <game platform="pc">
    <name>Left 4 Dead 2</name>
    <genre>Sci-Fi First-Person Shooter</genre>
    <releasedate>11/17/2009</releasedate>
  </game>
  <game platform="xbox">
    <name>Aliens vs. Predator</name>
    <genre>Action</genre>
    <releasedate>2/16/2010</releasedate>
  </game>
  <game platform="xbox">
    <name>Dynasty Warriors: Strikeforce</name>
    <genre>Action</genre>
    <releasedate>2/16/2010</releasedate>
  </game>
  <game platform="xbox">
    <name>Tropico 3</name>
    <genre>Other Strategy Games</genre>
    <releasedate>2/16/2010</releasedate>
  </game>
  <game platform="ps3">
    <name>Braid</name>
    <genre>2D Platform</genre>
    <releasedate>11/12/2009</releasedate>
  </game>
  <game platform="ps3">
    <name>Uncharted 2: Among Thieves</name>
    <genre>Modern Action Adventure</genre>
    <releasedate>10/13/2009</releasedate>
  </game>
  <game platform="ps3">
    <name>Assassin's Creed II</name>
    <genre>Historic Action Adventure</genre>
    <releasedate>11/17/2009</releasedate>
  </game>
</games>

في الأمثلة التي سبقت قمنا بإستخدام العنصر xsl:for-each حتى نقوم بعض العناصر الـ Children الناتجه من الـ select attribute الآن سنرى كيفية إستخدام الـ xsl:apply-templates، سيكون ملف الـ XSLT على النحو التالي

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>


  <xsl:template match="game">
    <p style="padding: 5px; filter: progid : DXImageTransform.Microsoft.Alpha(opacity=0);">
      <h4 style="color: #a3a3f0;">
        <xsl:value-of select="name"/>

        <xsl:choose>

          <xsl:when test="@platform = 'pc'">
            <img src="images/win.png" alt="Windows" style="vertical-align: middle; margin-left: 20px;" />
          </xsl:when>

          <xsl:when test="@platform = 'xbox'">
            <img src="images/xbox.png" alt="XBox 360" style="vertical-align: middle; margin-left: 20px;" />
          </xsl:when>

          <xsl:otherwise>
            <img src="images/ps3.png" alt="Play Station 3" style="vertical-align: middle; margin-left: 20px;" />
          </xsl:otherwise>

        </xsl:choose>

      </h4>
      <font style="font-size: 7pt; font-family: Tahoma; font-style:italic; font-wieght: bold;">
        [Genre: <xsl:value-of select="genre"/>] [Release Date: <xsl:value-of select="releasedate" />]
      </font>
    </p>
  </xsl:template>
</xsl:stylesheet>

في الناحية الأخرى (ملف الـ .aspx) سيكون الكود في الـ Design كالتالي :

<asp:Xml ID="gamesXmlApplyTemplates" runat="server" DocumentSource="~/games.xml" TransformSource="~/games_xslt_apply_templates.xslt" />

بعد أن رأينا كيفية عرض بيانات (محتوى) ملف XML سنتحدث عن طريقة عرض أو تنفيذ (Execute) ملف XSLT عن طريق المتصفح فقط، كل ما نحتاجه لعمل ذلك هو ملف XML وملف XSLT و إضافة السطر التالي

في ملف الـ XML :

<?xml-stylesheet type="text/xsl" href="xlst.xslt" version="1.0"?>

السطر السابق يتم إضافتخ مباشرة بعد السطر الخاص بتعريف المحتوى على أنه محتوى xml وهو

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

وأخيرا نضيف العنصر xsl:output والذي يحوي على method attribute في ملف الـ XSLT والذي من خلاله نقوم بتحديد نوع المخرج وهو إما text أو html أو xml أو name، سيكون ملف الـ XSL على هذا النحو

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" />

<xsl:template match="*">
	<xsl:apply-templates  />
</xsl:template>

<xsl:template match="game">
	<p>
		<h3><xsl:value-of select="name" /> (<xsl:value-of select="@platform" />)</h3>
		<span>
			[Genre: <xsl:value-of select="genre" />] [Release Date: <xsl:value-of select="releasedate" />]
		</span>
	</p>
</xsl:template>


</xsl:stylesheet>

في المرفقات ستجدوا ملف xslt و xml قم بتحميلهم و ثم قم بفتح ملف الـ xml عن طريق المتصفح.

أتمنى التوفيق للجميع

xml test.zip

1
#8

موضوع جيد Robatic و في انتظار المزيد

بالتوفيق ان شاء الله

#9

شكرا أفادك الله

رب اشرح لي صدري .......... ويسر لي أمري

#10

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

أخواني الكرام / أشكركم على مروركم الكريم فوالله لا تعلمون التأثير الإيجابي الذي يحدثه ذلك

في بداية الموضوع ذكرت أنه بإستخدام الـ XSLT تمكنك من قراءة ملف XML وتحويلة لملف XML ولكن بتركيب مختلف، وذكرت أيضا أنه يمكننا الإستفادة من هذه الميزة في عملية الدمج بين نظامين مختلفين (Integration) حيث أن الأول يصدر ملف XML بصورة مختلفة والثاني يقراء ملف XML بصورة مختلفة عن النظام الأول. يمكنك عن طريق الـ XSLT تحويل ما يصدرة النظام الأول إلى ما يقبله النظام الثاني. مثلا لو أخذنا ملف games.xml المطروح في المشاركات السابقه (سأسردة في الأسفل) نلاحظ ان هناك عنصر games وهو العنصر الجذري (root element) بداخلة عناصر بإسم game ويحوي attribute بإسم platform وبداخل كل عنصر game هناك عناصر أخرى مثل name وما إلى ذلك. ماذا لو أردنا تغيير تركيبة الملف بحيث أن نقوم بتحويل كل العناصر الموجوده داخل عنصر game إلى attribute بنفس اسم وقيمة العنصر الداخلي ؟ يمكنك قراءة ملف games.xml ومن ثم كتابته بالشكل الذي تريد برمجيا عن طريق XmlReader و XmlWriter. وأيضا يمكنك قراءته بعد أن يقترن بملف XSLT حيث أن عملية القراءة ستكون كما لو أن ملف الـ XML تغير ولكن في الواقع الملف ثابت لم يتغير وإنما إمتثل للقوانين والمواصفات الموجوده بملف الـ XSLT. ولكي تتضح الفكرة أكثر إليكم ملف games.xml وهو بالصورة القديمة

<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet type="text/xsl" href="xslt.xslt" version="1.0"?>

<games>
  <game platform="pc">
    <name>Dragon Age: Origions</name>
    <genre>Computer Role-Playing</genre>
    <releasedate>11/3/2009</releasedate>
  </game>
  <game platform="pc">
    <name>Mass Effect 2</name>
    <genre>Action Role-Playing</genre>
    <releasedate>1/26/2010</releasedate>
  </game>
  <game platform="pc">
    <name>Left 4 Dead 2</name>
    <genre>Sci-Fi First-Person Shooter</genre>
    <releasedate>11/17/2009</releasedate>
  </game>
  <game platform="xbox">
    <name>Aliens vs. Predator</name>
    <genre>Action</genre>
    <releasedate>2/16/2010</releasedate>
  </game>
  <game platform="xbox">
    <name>Dynasty Warriors: Strikeforce</name>
    <genre>Action</genre>
    <releasedate>2/16/2010</releasedate>
  </game>
  <game platform="xbox">
    <name>Tropico 3</name>
    <genre>Other Strategy Games</genre>
    <releasedate>2/16/2010</releasedate>
  </game>
  <game platform="ps3">
    <name>Braid</name>
    <genre>2D Platform</genre>
    <releasedate>11/12/2009</releasedate>
  </game>
  <game platform="ps3">
    <name>Uncharted 2: Among Thieves</name>
    <genre>Modern Action Adventure</genre>
    <releasedate>10/13/2009</releasedate>
  </game>
  <game platform="ps3">
    <name>Assassin's Creed II</name>
    <genre>Historic Action Adventure</genre>
    <releasedate>11/17/2009</releasedate>
  </game>
</games>

المطلوب تحويلة إلى الشكل التالي :

<?xml version="1.0" encoding="UTF-8"?>
<games>
  <game platform="pc" name="Dragon Age: Origions" genre="Computer Role-Playing" releasedate="11/3/2009"/>
  <game platform="pc" name="Mass Effect 2" genre="Action Role-Playing" releasedate="1/26/2010"/>
  <game platform="pc" name="Left 4 Dead 2" genre="Sci-Fi First-Person Shooter" releasedate="11/17/2009"/>
  <game platform="xbox" name="Aliens vs. Predator" genre="Action" releasedate="2/16/2010"/>
  <game platform="xbox" name="Dynasty Warriors: Strikeforce" genre="Action" releasedate="2/16/2010"/>
  <game platform="xbox" name="Tropico 3" genre="Other Strategy Games" releasedate="2/16/2010"/>
  <game platform="ps3" name="Braid" genre="2D Platform" releasedate="11/12/2009"/>
  <game platform="ps3" name="Uncharted 2: Among Thieves" genre="Modern Action Adventure" releasedate="10/13/2009"/>
  <game platform="ps3" name="Assassin's Creed II" genre="Historic Action Adventure" releasedate="11/17/2009"/>
</games>

سيكون ملف الـ XSLT بالشكل التالي :

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">    
    <games>
      <xsl:apply-templates />
    </games>
  </xsl:template>

  <xsl:template match="game">

    <game>

      <!-- Selecting any already existing attributes -->

      <xsl:for-each select="@*">

        <!-- Create an attribute with the same name & value of the current attribute -->

        <xsl:attribute name="{local-name()}">
          <xsl:value-of select="."/>
        </xsl:attribute>

      </xsl:for-each>

      <!-- Selecting any already exisiting elements -->

      <xsl:for-each  select="*">

        <!-- Create an attribute with the same name & value of the current element -->

        <xsl:attribute name="{local-name()}">
          <xsl:value-of select="."/>
        </xsl:attribute>

      </xsl:for-each>

    </game>

  </xsl:template>

</xsl:stylesheet>

لاحظ في الجزء الأول من ملف XSLT

<xsl:template match="/">    
    <games>
      <xsl:apply-templates />
    </games>
  </xsl:template>

قمنا بوضع العنصر xsl:apply-template داخل العنصر games حيث أن العنصر games سيكون هو العنصر الجذر في الملف النهائي، يمكنك إستبدالة بأي اسم آخر. نفس المبدئ ينطبق على العنصر game الموجود قبل العنصر xsl:for-each. وأيضا هناك تعبير جديد تم إستخدامه وهو local-name حيث أنها دالة خاصة بالـ XPath وتقوم بإرجاع اسم العنصر أو الـ attribute الحالي. الآن سوف نقوم بعرض النتائج على GridView ولكن سيكون الـ XPath مطابقا للتغيير الذي سيحدثه ملف الـ XSLT بمعني آخر سوف نتعامل على أساس أن العنصر game لا يحتوى إلا على attributes فقط، وهذا هو الكود :

<asp:GridView ID="gamesAttributeGridView" runat="server" DataSourceID="gamesXmlDataSourceAttribute"
            AutoGenerateColumns="false" Width="700px" CellPadding="5">
            <HeaderStyle BackColor="#a3a3f0" />
            <Columns>
                <asp:TemplateField HeaderText="Title">
                    <ItemTemplate>
                        <%# XPath("@name") %>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Genre">
                    <ItemTemplate>
                        <%# XPath("@genre") %>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Platform" ItemStyle-HorizontalAlign="Center" 
                    ItemStyle-VerticalAlign="Middle">
                    <ItemTemplate>
                        <%# XPath("@platform") %>
                    </ItemTemplate>
                </asp:TemplateField>
                <asp:TemplateField HeaderText="Release Date">
                    <ItemTemplate>
                        <%# XPath("@releasedate") %>
                    </ItemTemplate>
                </asp:TemplateField>
            </Columns>
        </asp:GridView>

        <asp:XmlDataSource ID="gamesXmlDataSourceAttribute" runat="server" DataFile="you_xml_file"
            TransformFile="your_xslt_file" XPath="/games/game" />

في الجزء الأول من هذا الموضوع قد كتبت التالي :

اقتباس
ملاحظة : عندما تستخدم العنصر xsl:if وتريد أن تفحص قيمة ما إذا كانت أكبر من عدد معين، لن يكون هناك مشكلة ولكن لو أستخدمة العلامة أصغر من وأردت أن تفحص قيمة ما إذا كانت أصغر من عدد معين فهذا سيؤدي إلى خطأ أجهل سببه. لو كان المطلوب منك هو فحص قيمة ما إذا كانت أصغر من عدد معين فقم بإستخدام العنصر xsl:choose.

لقد قمت بالبحث وتبين أن هناك أداة نفي وهي (!) يمكنك إستخدامها. آمل أن لا يكون ما ذكرت في الجزء الأول من هذا الموضوع قد سبب بعض الحيرة لكم وأتأسف لكم لتأخري في الرد بخصوص تحويل ملف XML من صيغة إلى صيغة جديدة عن طريق ملف XSLT.

بهذا أنهي الموضوع وآمل أن لا يكون هناك أي لبس وأرجوا من كل من لدية أي إستفسار أن لا يتردد بكتابة رد وأتمنى للجميع التوفيق والنجاح.

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