这个知识点其实非常简单。但是想把它写出来。
下面列举了三种方法。一是HTML模板+StreamReader(HTML模板);二是XSLT模板+SQL.Command.ExecuteXmlReader;三是XSLT模板+SQL.DataSet/DataTable
一:自己的理解:有一个模板(HTML页)文件,这个模板的几个地方是变量,然后在后台从这个模板文件读取文本,在有变量的地方用replace替换成想显示的值,这个值变可以从数据库中读取,从而实现了动态。然后将文本在写入到一个新的HTML页。生成HTML页。
关键的几点,
读出:要用StreamReader(path),它为指定的文件名(即模板文件名)初始化 StreamReader 类的新实例。通俗讲,就是从Path的文件中读取出文本,StreamReader 旨在以一种特定的编码输入字符,StreamReader 的默认编码为 UTF-8。其方法有ReadLine()。
而这个文本保存到哪里呢?肯定是放到一个字符变量中,我们用StringBuilder ,按行读,同样是字符,为什么不用String?因为String 对象是不可改变的。每次使用 System.String 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。如果要修改字符串而不创建新的对象,则可以使用
替换:很简单,将读取到模板的文本StringBuilder用Replace()替换下。
写入:要用StreamWriter(path),和StreamReader(path)想法,但是思想是一样。它的载体也是StreamReader类型的文本;具体方法为StreamWriter.WriteLine(StreamReader);
下面是个例子:
1。定义一个读取器,也就是一种文本,取代字符概念;
StringBuilder htmltext=new StringBuilder();
2。从模板文件中读取文本出来;可以参照帮助文档。
try
{
using (StreamReader sr = new StreamReader(Server.MapPath("htmltem.aspx")))
{
String line;
while ((line = sr.ReadLine()) != null)
{
htmltext.Append(line);
}
sr.Close();
}
}
catch
{ Response.Write("<Script>alert('读取文件错误')</Script>"); }
3。替代模板中的变量;这部分很灵活,可以将数据库中的数据读出来。下面简单些,是个数组。
string[] values=new string[4];
values[0] = "background='...jpg'";
values[1] = "#CCCCCC";
values[2] = "100px";
values[3] = "<marquee>模板生成的页面</marquee>";
for(int i=0;i<4;i++)
{
htmltext.Replace("$htmlvalue[" + i + "]", values[i]);
}
4。读入,将读出的文本经过部分替换后,读入一个新的HTML文档中。
try
{
using(StreamWriter sw=new StreamWriter(Server.MapPath("HTMLS/ohtml.html"),false,System.Text.Encoding.GetEncoding("GB2312")))
{ sw.WriteLine(htmltext);
sw.Flush();清除缓存区,并写入到基础流。
sw.Close();关闭基础流。
}
}
catch
{ Response.Write ("The file could not be wirte:"); }
注意读入的时候,要定义它的Encoding。
上面为C#的后台操作,模板前台的代码也要注意下:后台中$htmlvalue在前台的体现;可以使XSLT文件,aspx文件,ASP文件
<div>
<table $htmlvalue[0] >
<tr>
<td >
<span style="color: $htmlvalue[1];font-size: $htmlvalue[2]">$htmlvalue[3]</span>
</td>
</tr>
</table>
</div>
总结,这个思路很简单,模板的概念是个ASPX文件,我目前向从XML方面着手来研究。模板应该是XSLT文件,加油。
二:
补充:经过几天的研究,我打通了XML+XSLT模板生成HTML文件的路子,现在放到这里:
其实在我之前的一个文章当中写到过。现在再放进来,之前的那个可以生成,但是打不开。原应是没有关闭编写器。现在归纳如下。
using (SqlConnection con = new SqlConnection("Server=.;DataBase=HGSTUDY;uid=sa;pwd=yao"))
{
con.Open();
SqlCommand command = new SqlCommand(string.Format("select * from GL_STUDY where GS_STYNAME_ID={0} for xml auto,elements",id), con);
读:XmlReader reader = command.ExecuteXmlReader();
XPathDocument xpath = new XPathDocument(reader);
XslCompiledTransform xslcom = new XslCompiledTransform();
写:XmlTextWriter xtw = new XmlTextWriter(Server.MapPath("myhtml.html"), System.Text.Encoding.UTF8);
myhtml.html是可以覆盖的。
xslcom.Load(Server.MapPath("newxslt.xslt"));
xslcom.Transform(xpath, null,xtw);
reader.Close();
xtw.Close();
}
这个思路中模板的概念是xslt文件,因为是基于XML的方法。所以没有替换一说。适合查询页面的编写,其自动生成的页面可以覆盖,所以和前一个方法的实现用途不一样。
在newxslt.xslt的定义:
<?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"/>
<xsl:template match="/">
<html>
<head>
<title>生成的HTML页</title>
</head>
<body>
<table >
<div>
<xsl:for-each select="//GL_STUDY">
<tr align="center">
<th onmousemove="this.bgColor='#ffccff'" onmouseout="this.bgColor='white'" style="font-size:12px">
<xsl:value-of select="GS_CONENT"/>
</th>
</tr>
</xsl:for-each>
</div>
<div><input type="button" value="click me!"/> </div>
<div>
</div>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
三:
可以看出,在上面的地思路中,存在一个缺陷,就是在for-each的节点值为数据库的表名,这样就有了局限,于是想到了是不是可以让这个节点灵活些,也就是可以自己来定义呢?所以经过研究,我发现可以采取DataSet+DataTable,因为DataSet的临时表的表名可以随便定义。所以可以把它拿过来。
上面的例子数据库查询语句,select ....where ..... for xml auto,elements我们用SqlCommand的ExecuteXmlReader方法,返回的是xmlReader类型的值,用该值来初始化XPathDocument对象;而当我们用DataSet是无法通过一些方法返回一个xmlReader类型的值得,DataSet 只有GetXml方法,返回一个XML字符串而已,如何将这个字符串来初始化XPathDocument对象呢?
现在只要解决了这个问题就可以:DataSet.GetXml()返回的XML字符串不可以形成xmlReader,但是可以初始化XmlTextReader ;其实用XmlTextReader 的XML数据也可以初始化XPathDocument对象也可以。下面的语句便是了:
利用重载:使用指定的字符串(DataSet.GetXml())、XmlNodeType 和 XmlParserContext (提供 XmlReader 分析 XML 片段所需的所有上下文信息)初始化 XmlTextReader 类的新实例.
关于XmlParserContext 得初始化:用指定的 XmlNameTable、XmlNamespaceManager、xml:lang 和 xml:space 值初始化 XmlParserContext 类的新实例。
XmlParserContext context = new XmlParserContext(null,null, null, XmlSpace.None);
XmlTextReader read = new XmlTextReader(ds.GetXml(), XmlNodeType.Element, context);
因此,要生成DataSet+DataTable;先看代码:
using (SqlConnection con = new SqlConnection("Server=.;DataBase=HGSTUDY;uid=sa;pwd=yao"))
{
con.Open();
SqlCommand command = new SqlCommand(string.Format("select * from GL_STUDY where GS_STYNAME_ID={0}", id), con);
command.CommandType = CommandType.Text;
DataSet ds = new DataSet("DATASET");
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = command;
sda.Fill(ds, "DATATABLE");
下面是转换,将DataSet和XSLT结合
XmlParserContext context = new XmlParserContext(null,null, null, XmlSpace.None);
XmlTextReader read = new XmlTextReader(ds.GetXml(), XmlNodeType.Element, context);
[以上两句也可以是StringReader,StringReader read = new StringReader(ds.GetXml());]
XPathDocument xpath = new XPathDocument(read);
XslCompiledTransform xslcom = new XslCompiledTransform();
xslcom.Load(Server.MapPath("newxslt.xslt"));
下面是变现形式,可以生成其他HTML文件,也可以在当前的页面显示出来,根据需求而定
1。下面三句是生成为HTML文件
XmlTextWriter xtw = new XmlTextWriter(Server.MapPath("....html"), System.Text.Encoding.UTF8);
xslcom.Transform(xpath, null, xtw);
xtw.Close();
2。下面三句是在当前页面显示
TextWriter xw = new StringWriter();
xslcom.Transform(xpath, null, xw);
Response.Write(xw);
3。记得关闭
read.Close();
}
在思考工程中,关键就是1。DataSet.GetXml()返回一个XML的字符串。是String类型。关键2。就是对XPathDocument初始化的XML数据来源不同,上一个的来源是XmlReader,该XmlReader也就是SqlCommand.ExecuteXmlReader();而这个来源是XmlTextReader,该XmlTextReader由DataSet.GetXml()+一个XmlParserContext初始化。
最后附上newxslt.xslt的不同代码:<xsl:for-each select="/DATASET/DATATABLE">
<tr align="center">
<th onmousemove="this.bgColor='#ffccff'" onmouseout="this.bgColor='white'" style="font-size:12px">
<xsl:value-of select="GS_CONENT"/>
</th>
</tr>
</xsl:for-each>
2010-2-2补充:
在以上XSLT动态生成的HTML文件中,如果有JS脚本,页面打开的时候,浏览器就会提示"为了有利于保护安全性,Internet Explorer已限制此网页运行可以访问计算机的脚本或ActiveX控件.请单击这里获取选项...",这个提示是我想隐藏掉的.就是因为在HTML文件里缺少一句
在XSLT文件里:
<xsl:output method="html" version="4.0" indent="yes"/>
<?DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"?>
<!-- saved from url=(0022)http://blog.csdn.net/electroniXtar/ -->
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>...</head><body>...</body></html>
但是如果将这句照抄放到XSLT文件中,就不会保存成功,怎么办?要将这句话改成前后为两个问号.这样的话,就可以在HTML文件中随意用JS脚本了.
但是我在用Altova XMLSpy保存XSLT文件的时候,发现中文版的Altova XMLSpy保存后,会有问题,只能用英文版的Altova XMLSpy.