动态生成HTML文件记录

这个知识点其实非常简单。但是想把它写出来。
下面列举了三种方法。一是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 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间。如果要修改字符串而不创建新的对象,则可以使用 System.Text.StringBuilder 类.
StringBuilder,具体方法是用StringBuilder.Append(StreamReader)。这个类在帮助文档中定义:StringBuilder实现一个 TextReader,使其以一种特定的编码从字节流中读取字符。而TextReader表示可读取连续字符系列的读取器。也就是我们说的文本,其实是个读取器。它里面放的是文本。
替换:很简单,将读取到模板的文本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);  
[以上两句也可以是StringReaderStringReader  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文件里缺少一句

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

 在XSLT文件里:

代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<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.

原文地址:https://www.cnblogs.com/winvay/p/1323927.html