ASP.NET中自动生成XML文件并通过XSLT显示在网页中的方法

XML是一种很方便的描述数据的方法,其格式也比较接近HTML,因此就有了想把XML直接通过网页的形式显示在浏览器中的想法。但是直接打开XML文件,浏览器是无法解析的,只是把文档的结构原封不动地呈现出来而已。例如,我们有一个学生课程表的文档schedule.xml,用浏览器直接打开是这个样子的。(不过不知道为什么只能在IE中打开,在chrome中打开后无法显示,求教)

那么如何将XML文档能够以比较容易看懂的方式显示在网页上呢?通过查找资料以后得知有一种XML文档叫做XSLT(EXtensible Stylesheet Language Transform,可扩展样式表语言转换)。详见http://www.w3school.com.cn/xsl/index.asp

接着就是要选择我们比较容易看懂的形式了。由于是课程表,我们当然首选采用表格的形式展现。但是在确定展现的具体手段时却遇到了瓶颈。究竟是采用课程驱动、还是时间驱动的形式?经过反复试验和调试,终于确定以时间为驱动,采用逐单元格填充的方式进行转换。最终生成的XSLT代码如下(部分):

  1. <?xml version="1.0" encoding="gb2312"?>
  2.  
  3. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  4.  
  5.   <xsl:template match="/">
  6.     <html>
  7.       <body>
  8.         <h2>我的课程表</h2>
  9.         <table border="1">
  10.           <tr bgcolor="#9acd32">
  11.             <th></th>
  12.             <th align="center">1</th>
  13.             <th align="center">2</th>
  14.             <th align="center">3</th>
  15.             <th align="center">4</th>
  16.             <th align="center">5</th>
  17.             <th align="center">6</th>
  18.             <th align="center">7</th>
  19.             <th align="center">8</th>
  20.             <th align="center">9</th>
  21.             <th align="center">10</th>
  22.             <th align="center">11</th>
  23.           </tr>
  24.           <tr>
  25.             <td>周一</td>
  26.             <xsl:for-each select="schedule/day">
  27.               <xsl:if test="week = '周一'">
  28.                 <td>
  29.                   <xsl:for-each select="course">
  30.                     <xsl:choose>
  31.                       <xsl:when test="time = 1">
  32.                         <xsl:value-of select="name"></xsl:value-of>
  33.                       </xsl:when>
  34.                       <xsl:otherwise>
  35.  
  36.                       </xsl:otherwise>
  37.                     </xsl:choose>
  38.                   </xsl:for-each>
  39.                 </td>
  40.                 ...
  41.             </xsl:if>
  42.             </xsl:for-each>
  43.           </tr>
  44.           ....
  45.           </table>
  46.       </body>
  47.     </html>
  48.   </xsl:template>
  49.  
  50. </xsl:stylesheet>

接下来就是要将XML和XSLT结合起来了。

XML输出有两种方式,一种是流的形式,另一种是文件的形式。采用流的方式其实并不适用,因为文档流默认是填充在一个文件的前面的,如果是采用HTML或者ASPX等文件,会影响整个文档的结构。因此采用文件的方法,即将所有XML节点写入一个文件,并保存在服务器上。当然,随着用户数量的增多,生成的XML文件必然会越来越多,所以还得增加一个定期删除的机制,这个不在我们讨论范围之内因此不再赘述。

之前从数据库中读出数据并写入一个List的方法如下:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Configuration;
  6. using System.Xml;
  7. using System.Web.UI;
  8. using System.Web.UI.WebControls;
  9.  
  10. namespace CampusSystem
  11. {
  12.     public enum Weekday { 周一, 周二, 周三, 周四, 周五 };
  13.  
  14.     public struct CourseToXML
  15.     {
  16.         public string course_id;
  17.         public string name;
  18.         public Weekday week;
  19.         public string[] times;
  20.     }
  21.  
  22.     public static class ScheduleMaker
  23.     {
  24.         static string connString = ConfigurationManager.ConnectionStrings["CampusConnectionString"].ConnectionString;
  25.         static CampusDBDataContext db = new CampusDBDataContext(connString);
  26.  
  27.         public static List<CourseToXML> MakeScheduleList(string uid)
  28.         {
  29.             string course_id = string.Empty;
  30.             string name = string.Empty;
  31.             string allTime = string.Empty;
  32.  
  33.             CourseToXML ctx = new CourseToXML();
  34.             List<CourseToXML> ctxl = new List<CourseToXML>();
  35.  
  36.             var mySchedule = from ms in db.Schedule where ms.student_id == uid select ms.course_id;
  37.             foreach (string cid in mySchedule)
  38.             {
  39.                 var courseInfo = from ci in db.Course where ci.course_id == cid select new { ci.course_id, ci.name, ci.time };
  40.                 foreach (var c in courseInfo)
  41.                 {
  42.                     course_id = c.course_id;
  43.                     name = c.name;
  44.                     allTime = c.time;
  45.                     string[] oneTimes = allTime.Split(';');
  46.                     foreach (string oneTime in oneTimes)
  47.                     {
  48.                         string[] weekAndTime = oneTime.Split(',');
  49.                         string week = weekAndTime[0];
  50.                         string[] times = weekAndTime[1].Split('.');
  51.  
  52.                         ctx.course_id = course_id;
  53.                         ctx.name = name;
  54.  
  55.                         ctx.times = times;
  56.                         switch (week)
  57.                         {
  58.                             case "周一":
  59.                                 ctx.week = Weekday.周一;
  60.                                 break;
  61.                             case "周二":
  62.                                 ctx.week = Weekday.周二;
  63.                                 break;
  64.                             case "周三":
  65.                                 ctx.week = Weekday.周三;
  66.                                 break;
  67.                             case "周四":
  68.                                 ctx.week = Weekday.周四;
  69.                                 break;
  70.                             case "周五":
  71.                                 ctx.week = Weekday.周五;
  72.                                 break;
  73.                             default:
  74.                                 break;
  75.                         }
  76.  
  77.                         ctxl.Add(ctx);
  78.                     }
  79.                 }
  80.             }
  81.             ctxl.Sort((CourseToXML ctxA, CourseToXML ctxB) =>
  82.             {
  83.                 if (ctxA.week == ctxB.week)
  84.                     return ctxA.times[0].CompareTo(ctxB.times[0]);
  85.                 else
  86.                     return ctxA.week.CompareTo(ctxB.week);
  87.             });
  88.  
  89.             return ctxl;
  90.  
  91.         }
  92.    }
  93. }

需要查询的页面schedule.aspx如下:(前提是需要有一个存放生成后的html文档的html文件。)

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.UI;
  6. using System.Web.UI.WebControls;
  7. using System.Xml;
  8. using System.Xml.Xsl;
  9.  
  10. namespace CampusSystem
  11. {
  12.     public partial class schedule : System.Web.UI.Page
  13.     {
  14.         string uid;
  15.  
  16.         protected void Page_Load(object sender, EventArgs e)
  17.         {
  18.             uid = GetUID();
  19.             List<CourseToXML> list = ScheduleMaker.MakeScheduleList(uid); //读出数据库中数据
  20.             MakeScheduleXML(list, uid); //生成XML文档
  21.  
  22.             XslCompiledTransform xslt = new XslCompiledTransform();
  23.             xslt.Load(Server.MapPath("schedule.xsl"));
  24.             xslt.Transform(Server.MapPath("Schedule/schedule_" + uid + ".xml"), Server.MapPath("schedule.html"));
  25.        //这个方法就是将指定的XML文件通过指定的XSL文件转换以后生成到一个指定的html文件中。
  26.  
  27.             Response.Redirect("schedule.html");
  28.         }
  29.  
  30.         private string GetUID()
  31.         {
  32.             string uid = string.Empty;
  33.             HttpCookie cookie = Request.Cookies["LOGIN"];
  34.             if (cookie != null) // 若Cookie不为空,则采用cookie
  35.             {
  36.                 uid = cookie["uid"];
  37.             }
  38.             else // 否则采用Session
  39.             {
  40.                 uid = (string)Session["uid"];
  41.             }
  42.             return uid;
  43.         }
  44.  
  45.         protected void MakeScheduleXML(List<CourseToXML> list, string uid)
  46.         {
  47.             XmlDocument xmlDoc = new XmlDocument();
  48.             XmlDeclaration decl = xmlDoc.CreateXmlDeclaration("1.0", "utf-8", null);
  49.             xmlDoc.AppendChild(decl);
  50.  
  51.             XmlElement root = xmlDoc.CreateElement("schedule");
  52.             xmlDoc.AppendChild(root);
  53.  
  54.  
  55.             for (int weekday = 0; weekday < 5; weekday++)
  56.             {
  57.                 XmlNode nodeDay = xmlDoc.CreateElement("day");
  58.                 root.AppendChild(nodeDay);
  59.                 XmlNode week = null;
  60.                 switch (weekday)
  61.                 {
  62.                     case 0:
  63.                         week = xmlDoc.CreateElement("week");
  64.                         week.InnerText = Weekday.周一.ToString();
  65.                         break;
  66.                     case 1:
  67.                         week = xmlDoc.CreateElement("week");
  68.                         week.InnerText = Weekday.周二.ToString();
  69.                         break;
  70.                     case 2:
  71.                         week = xmlDoc.CreateElement("week");
  72.                         week.InnerText = Weekday.周三.ToString();
  73.                         break;
  74.                     case 3:
  75.                         week = xmlDoc.CreateElement("week");
  76.                         week.InnerText = Weekday.周四.ToString();
  77.                         break;
  78.                     case 4:
  79.                         week = xmlDoc.CreateElement("week");
  80.                         week.InnerText = Weekday.周五.ToString();
  81.                         break;
  82.                     default:
  83.                         break;
  84.                 }
  85.                 nodeDay.AppendChild(week);
  86.  
  87.                 foreach (CourseToXML ctx in list)
  88.                 {
  89.                     XmlNode course = null;
  90.                     if (weekday == (int)(ctx.week))
  91.                     {
  92.                         course = xmlDoc.CreateElement("course");
  93.                         foreach (string t in ctx.times)
  94.                         {
  95.                             XmlNode time = xmlDoc.CreateElement("time");
  96.                             time.InnerText = t;
  97.                             course.AppendChild(time);
  98.                         }
  99.                         XmlNode name = xmlDoc.CreateElement("name");
  100.                         name.InnerText = ctx.name;
  101.                         course.AppendChild(name);
  102.                         nodeDay.AppendChild(course);
  103.                     }
  104.  
  105.                 }
  106.             }
  107.  
  108.             xmlDoc.Save(Server.MapPath("Schedule/schedule_" + uid + ".xml"));
  109.         }
  110.     }
  111. }

运行以后自动返回所生成的html文档,就能看到结果了。

虽然还略显简陋就是了,当然,这个可以通过css来控制,这里也不再赘述。

总结

为了完成这个任务,采取了一切能想到的方法。包括XMLDocument,XSLT转换,LINQ,泛型,Lambda表达式,还有XML本身的设计等等,很多知识的大综合。也是对自己学习能力和综合应用能力一个提高。真正的成就感就是在这样不断解决问题的过程中产生的,也是给了我继续把项目做好的动力。

posted @ 2013-05-29 09:25  飞鸟_Asuka  阅读(616)  评论(0编辑  收藏  举报