• 动态生成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.

  • 相关阅读:
    设计模式
    软件的架构与设计模式之经典架构模式简介
    Rose与PowerDesigner:两款建模工具的对比
    C#中Socket多线程编程实例 [转载]
    C#串口控制
    .NET反射、委托技术与设计模式
    求多个数的质因子
    求单个数的欧拉函数
    基本欧拉函数
    hdu 2157(矩阵的快速幂)
  • 原文地址:https://www.cnblogs.com/winvay/p/1323927.html
Copyright © 2020-2023  润新知