[转载]如何将List转换相应的Html(xsl动态转换)(二) – JasenKin – 博客园.
紧跟着上一篇随笔,本文主要涉及到如何将xml与xsl动态转换成html,这个才是最关键的地方,所有的内容都是围绕这个主题来进行开展的。根据指定的xsl样式将List<T>转换相应的Html,相关的随笔如下:
(一)、将List<T>转换成DataTable。
(二)、将Xml与Xsl动态转换成Html。
(三)、设置以及控制Xsl的内容样式。
二、XslTransform的具体实现
XslTransform主要的职责为:将xml与xsl动态转换成html。其中,XslCompiledTransform 提供了很多方法可以进行相关的转换,但使用起来并不是十分方便,因此必须在该基础上来对目前的类进行相关封装以及提取。具体的代码如下:
1 public class XslTransform : IDisposable 2 { 3 public StringWriter StringWriter 4 { 5 get ; 6 private set ; 7 } 8 9 public StringReader XmlStringReader 10 { 11 get ; 12 private set ; 13 } 14 15 public StringReader XslStringReader 16 { 17 get ; 18 private set ; 19 } 20 21 public XslTransform() 22 { 23 this .StringWriter = new StringWriter(); 24 } 25 26 public string Transfer( string xmlText, string xslText) 27 { 28 if ( string .IsNullOrWhiteSpace(xmlText) 29 || string .IsNullOrWhiteSpace(xslText)) 30 { 31 return string .Empty; 32 } 33 this .XmlStringReader = new StringReader(xmlText); 34 this .XslStringReader = new StringReader(xslText); 35 36 return TransferXmlAndXslToHtml(); 37 } 38 39 private string TransferXmlAndXslToHtml() 40 { 41 try 42 { 43 using (XmlTextWriter writer = new XmlTextWriter( this .StringWriter)) 44 { 45 return ToHtml(writer); 46 } 47 } 48 catch 49 { 50 return string .Empty; 51 } 52 } 53 54 private string ToHtml(XmlTextWriter writer) 55 { 56 XslCompiledTransform xslTransform = new XslCompiledTransform(); 57 xslTransform.Load(XmlReader.Create( this .XslStringReader)); 58 xslTransform.Transform(XmlReader.Create( this .XmlStringReader), writer); 59 60 return this .StringWriter.ToString(); 61 } 62 63 #region IDisposable 成员 64 65 public void Dispose() 66 { 67 this .Dispose( true ); 68 GC.SuppressFinalize( this ); 69 } 70 71 private void Dispose( bool disposing) 72 { 73 if ( this .StringWriter != null ) 74 { 75 this .StringWriter.Dispose(); 76 } 77 if ( this .XslStringReader != null ) 78 { 79 this .XslStringReader.Dispose(); 80 } 81 if ( this .XmlStringReader != null ) 82 { 83 this .XmlStringReader.Dispose(); 84 } 85 } 86 87 #endregion 88 } |
XslTransform 类主要的方法为54-61行的代码,如下所示:
54 private string ToHtml(XmlTextWriter writer) 55 { 56 XslCompiledTransform xslTransform = new XslCompiledTransform(); 57 xslTransform.Load(XmlReader.Create( this .XslStringReader)); 58 xslTransform.Transform(XmlReader.Create( this .XmlStringReader), writer); 59 60 return this .StringWriter.ToString(); 61 } |
第57行加载XSL的样式文本,58行在原有基础上将XML转换成XmlTextWriter对象。其中XmlTextWriter在初始化时,StringWriter对象作为参数传递进去,如以下的43行代码:
43 using (XmlTextWriter writer = new XmlTextWriter(this.StringWriter))
因此直接返回this.StringWriter.ToString();就获取到了我们所需的Html了。
其次,XslTransform 类还有一个注意的要点:实现IDisposable接口主要是将用到的资源及时释放掉,避免造成其他影响。
三、Xsl文件的设置以及添加到资源文件中
(1)创建MapperInfoXslContent.xslt样式文件,内容如下(目前使用最简单的,不做任何处理的样式文件):
<!--?xml version="1.0" encoding="utf-8"?--> demo < table > < tbody > < tr > < td > < table style = "border-collapse: collapse;" border = "1px" cellspacing = "0px" bordercolor = "#000000" > < tbody > < tr bgcolor = "#9acd32" > < th width = "80" >Name</ th > < th width = "80" >Value</ th > < th width = "80" >Percent</ th > < th width = "230" >CreatedTime</ th > < th width = "60" >IsActive</ th > < th width = "190" >TargerUrl</ th > </ tr > < tr > < td width = "80" bgcolor = "#ff00ff" ></ td > < td width = "80" ></ td > < td width = "80" bgcolor = "#ff00ff" ></ td > < td width = "230" ></ td > < td width = "60" bgcolor = "#ff00ff" ></ td > < td width = "190" ></ td > </ tr > </ tbody > </ table > </ td > </ tr > </ tbody > </ table > |
(2)然后再创建XslResource.resx资源文件,将MapperInfoXslContent.xslt样式文件添加到XslResource.resx资源文件中,如下图所示:
四、转换后的效果
经过转换后得到的Html显示效果如下(测试过程中可以以HTML格式来查看字符串):
五、相关的单元测试
示例的单元测试代码如下(仅做了一些最基础的测试,验证内容是否存在):
[TestMethod()] public void TransferTest() { string xmlText = GetXmlText(); string xslText = XslResource.MapperInfoXslContent; string htmlContent = string .Empty; using (XslTransform xslTransform = new XslTransform()) { htmlContent = xslTransform.Transfer(xmlText, xslText); } Assert.IsTrue(! string .IsNullOrWhiteSpace(htmlContent)); Assert.IsTrue(htmlContent.Contains( "true" )); Assert.IsTrue(htmlContent.Contains( "false" )); for ( int index = 0; index < 3; index++) { Assert.IsTrue(htmlContent.Contains( string .Concat( "MapperInfoIndex" , index.ToString()))); Assert.IsTrue(htmlContent.Contains( string .Format( @"www.codeplex.com?Id={0}" , index))); Assert.IsTrue(htmlContent.Contains(index.ToString())); } } private string GetXmlText() { List entities = CreateMapperInfos(3); DataTable dataTable = EntityMapper.ToDataTable(entities); DataSet dataSet = new DataSet( "DataSet" ); dataSet.Tables.Add(dataTable); return dataSet.GetXml(); } private List CreateMapperInfos( int count) { List entities = new List(); for ( int index = 0; index < count; index++) { entities.Add( new MapperInfo() { Name = string .Concat( "MapperInfoIndex" , index.ToString()), IsActive = (index % 2 == 0 ? true : false ), CreatedTime = DateTime.Now, Value = index, Percent = GetPercent(index), TargetUrl = string .Format( @"www.codeplex.com?Id={0}" , index) }); } return entities; } private decimal ? GetPercent( int index) { if (index % 2 == 0) { return index; } return null ; } |
六、总结
上面涉及的仅仅是其中的一种,代码应该是比较精简的。还有另外一种采用XPathNavigator的,也就是笛子说的:“如果使用 XmlWriter 或 XmlDocument,则可以避开这个问题。另外,XslCompiledTransform.Transform 方法重载了几个版本中,如果我没记错的话,最应优先使用的是xml数据源为 XPathNavigator 的版本。”。关于这种情况,可以通过XmlDocument来创建相关的XPathNavigator对象,即:XPathNavigator navigator = XmlDocument.DocumentElement.CreateNavigator(),这种版本的我也重写了一份,但是好像没有转换成功,因此 就采用这种模式了。下一篇主要涉及到XSL样式的设计以及相关的函数、模板的应用。