在开发Web Control的时候,经常需要在源代码中嵌入一些HTML代码, 比如这样(代码片段):
protected override void RenderContents(HtmlTextWriter output) { SPList myList = GetListByName(List); if (myList != null) { uint currentLanguageCode = getCurrentLanguageCode(); output.WriteBeginTag("ul"); output.WriteAttribute("class", "lng"); output.WriteLine(HtmlTextWriter.TagRightChar);
foreach (SPListItem item in myList.Items) { if (uint.Parse((string)item["Language Code"]) != getCurrentLanguageCode()) { output.WriteBeginTag("li"); output.WriteAttribute("class", (string)item["CSS Class"]); output.WriteLine(HtmlTextWriter.TagRightChar); output.WriteBeginTag("a"); output.WriteAttribute("href", ((Microsoft.SharePoint.Publishing.Fields.LinkFieldValue)item["Language URL"]).NavigateUrl); output.WriteLine(HtmlTextWriter.TagRightChar); output.Write((string)item["Title"]); output.WriteEndTag("a"); output.WriteEndTag("li"); } } output.WriteEndTag("ul"); } }
这个控件的HTML会输出成类似这样:
<ul class="lng"> <li class="en"> <a href="real-url-of-en">EN</a> </li> <li class="fr"> <a href="real-url-of-fr">FR</a> </li> </ul>
但是这样做有个问题,假如我们想改变这个web control的表现,比如把CSS Class从“lng” 改为“language”,那么我们就必须要在这个代码里面修改,并且需要重新编译,这样就带来了极大的不方便。我们需要一种能够不需要重新编译代码就可以改变HTML的方法。 这篇文章就介绍一种这样的方法,解决方案是XML + XSL
原理是,在上面方法中,我们不直接负责HTML输出,而是我们构建一个XML文件在内存中,然后我们需要自己编写一个XSL文件来定义这个XML的表现。
具体这样:(一共两步) 1。 改写上面方法为:
protected override void RenderContents(HtmlTextWriter output) { SPList myList = GetListByName(List); if (myList != null) { try { XslCompiledTransform transformer = new XslCompiledTransform(); string s = SPUtility.GetGenericSetupPath("TEMPLATE\\LAYOUTS") + XslFileRelativeUrl; transformer.Load(s); StringWriter result = new StringWriter(); XmlDocument mydoc = BuildXML(myList); transformer.Transform(mydoc, null, result); output.WriteLine(result.ToString()); } catch (Exception ex) { Page.Response.Write(ex.Message); } } }
其中的BuildXML()方法为:
// <languages> // <language title="EN" code="1033" cssclass="en" url="en-url" /> // <language title="FR" code="1036" cssclass="fr" url="fr-url" /> // </languages> public XmlDocument BuildXML(SPList myList) { if (myList != null) { XmlDocument doc = new XmlDocument(); XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null); doc.AppendChild(docNode); XmlNode languagesNode = doc.CreateElement("languages"); doc.AppendChild(languagesNode);
foreach (SPListItem item in myList.Items) { if (uint.Parse((string)item["Language Code"]) != getCurrentLanguageCode()) { XmlNode languageNode = doc.CreateElement("language");
XmlAttribute languageAttribute = doc.CreateAttribute("title"); languageAttribute.Value = (string)item["Title"]; languageNode.Attributes.Append(languageAttribute); languageAttribute = doc.CreateAttribute("code"); languageAttribute.Value = (string)item["Language Code"]; languageNode.Attributes.Append(languageAttribute); languageAttribute = doc.CreateAttribute("cssclass"); languageAttribute.Value = (string)item["CSS Class"]; languageNode.Attributes.Append(languageAttribute); languageAttribute = doc.CreateAttribute("url"); languageAttribute.Value = ((Microsoft.SharePoint.Publishing.Fields.LinkFieldValue)item["Language URL"]).NavigateUrl; languageNode.Attributes.Append(languageAttribute); languagesNode.AppendChild(languageNode); } } return doc; } else return null; }
2. 定义XSL文件:
<?xml version="1.0" encoding="UTF-8" ?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" encoding="UTF-8" indent="yes"/> <xsl:template match="/"> <ul class="lng"> <xsl:for-each select="languages/language"> <li class="{@cssclass}"> <a href="{@url}"> <xsl:value-of select="@title"/> </a> </li> </xsl:for-each> </ul> </xsl:template> </xsl:stylesheet>
这样就好了,以后想改HTML就直接改上面的XSL文件就可以了,再也不用重新编译了。而且这样做就把表现层的东西从代码中分离了,比较符合现代的软件设计思想。 可以看到上面这个控件是在SharePoint中用的,但是其思想完全不局限于SharePoint
|