zoukankan      html  css  js  c++  java
  • 小说下载阅读器_章节保存为XML并显示

    这篇文章主要是讲程序中对XML,XSLT,XSD,JS的简单应用。

    1.当小说的章节都下载完毕,章节内容经过过滤,去除多余的html标记和其它垃圾信息,变成干净的文本内容。怎么保存这些章节内容呢?

    1)解决方法:将所有章节依次写入同一个文本文件,并将小说名作为文件名。

    优点:
    通用性最好,不管是PC平台还是手机、平板电脑都能直接阅读,且人可直接阅读。
    缺点:
    如果想分离每章或者将文本文件格式转成其它格式,解析相对麻烦。

    2)解决方法:将所有章节,分章节依次写入同一个xml文件,并将小说名作为文件名。

    优点:
    由于xml文件是结构性的,通用性也很强,可轻易转成其它任意格式,且章节之间本身也是分隔的
    缺点:
    在于由于多了额外的信息,xml会比文本文件稍大一些。

    3)解决方法:将将所有章节,分章节写入数据库。

    优点:
    数据库的优点,不用多说,查询检索很方便。
    缺点:
    当数据多了,数据库也会变大。

    我采用的是第二种方法,原因如下

    1.暂时减少对数据库的依赖(后面的进化版,可能会用数据库存储章节内容)
    2.虽然文本文件的通用性是最高的,但我需要在window和linux上看小说,或者是手机上,手机上一般都需要安装阅读器,其实很多格式都支持,这个不是问题,关键在于window和linux上阅读,如果只是用普通编辑器来看文本小说,可以看,但是视觉效果真是很烂,为了统一windows和linux上的视觉效果,干脆就用xml作为中间格式,最终都在浏览器里面观看。

    2.小说要保存的要素:小说名称,章节名,章节内容,卷名以及其它附加信息

    1)XML格式例子如下:

     1 <?xml version="1.0" encoding="GB2312"?>
     2 <Article Name="盘龙" CreateTime="2012-01-01 00:00:00">
     3     <Part Index="第一章 小镇的早晨"  Volume="盘龙之戒">
     4            章节内容.......................
     5     </Part>
     6     <Part Index="第二章 龙血战士家族(上)"  Volume="盘龙之戒">
     7     ;;段落内容........;;段落内容。;;段落内容。;;段落内容。;;段落内容。;;段落内容。;;段落内容。
     8     </Part>
     9     <Part Index="第三章 龙血战士家族(下)"  Volume="盘龙之戒">
    10            <img src="http://img.58xs.com/gif/195/195623/18276026/13028469.gif" />//如果有图片就是这样的
    11     </Part>
    12 </Article>

    C#如何将字符串保存为xml,请参考System.Xml命名空间下的类,或者用linq to xml都行,更或者直接string拼凑都可以,代码就不写了。

    2)用xsd 来定义xml的schema:

     1 <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
     2     <xs:element name="Img">
     3         <xs:complexType>
     4             <xs:attribute name="Src" type="xs:anyURI" use="required"/>
     5         </xs:complexType>
     6     </xs:element>
     7     <xs:element name="Part">
     8         <xs:complexType mixed="true">
     9             <xs:sequence>
    10                 <xs:element ref="Img" minOccurs="0" maxOccurs="unbounded"/>
    11             </xs:sequence>
    12             <xs:attribute name="Index" type="xs:string" use="required"/>
    13             <xs:attribute name="Volume" type="xs:string" use="optional"/>
    14         </xs:complexType>
    15     </xs:element>
    16     <xs:element name="Article">
    17         <xs:complexType>
    18             <xs:sequence>
    19                 <xs:element ref="Part" maxOccurs="unbounded"/>
    20             </xs:sequence>
    21             <xs:attribute name="Name" type="xs:string" use="required"/>
    22             <xs:attribute name="CreateTime" type="xs:dateTime" use="optional"/>
    23         </xs:complexType>
    24     </xs:element>
    25 </xs:schema>

    以下是基本的解释

    Article.Name是小说名称 ,CreateTime是xml文件最后保存时间
    Part.Index是章节名称,Volume是卷名
    再就是Part的内容要么是文字,要么是Img图片

    3.如何显示保存到文件中章节内容呢?这里用xslt将xml文件转化成html进行显示

    先显示效果图:

    上述两幅图可以看出,显示部分主要分为三大块:

    1)第一块是第一幅图的最上的章节索引链接,可以在这块跳转到你需要观看的章节去
    2)第二块是第一幅图的下半部分,就是小说的正文,每一章节对应一个区块,每一章节都可以向前一章和后一章跳转。
    3)第三块是第二幅图的右半边,红色字的部分,可以对页面背景色和字体,以及页面自动滚动速度进行设置。

    当你写好xslt文件的时候,可以在xml文件第一行后面加上一句话区引用这个xslt文件,就可以让xml在浏览器中按照xslt规定显示

    <?xml-stylesheet type="text/xsl" href="Article.xslt"?>

    下面给出xslt的源码:

      1 <?xml version="1.0" encoding="GB2312"?>
      2 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      3     <!--
      4     <xsl:import href="function.xsl"/>
      5 -->
      6     <xsl:variable name="SplitToken">;;</xsl:variable>
      7     <xsl:template match="/">
      8         <html>
      9             <head>
     10                 <title>
     11                     <xsl:value-of select="/Article/@Name"/>
     12                 </title>
     13             </head>
     14             <link type="text/css" href="ui_a.css" rel="stylesheet"/>
     15             <body>
     16                 <xsl:choose>
     17                     <xsl:when test="count(/Article/*)>=1">
     18                         <a class="title" name="0">
     19                             <xsl:value-of select="/Article/@Name"/>
     20                         </a>
     21                         <br/>
     22                         <br/>
     23                         <xsl:if test="count(//Part)>1">
     24                             <xsl:call-template name="PartIndex"/>
     25                         </xsl:if>
     26                         <br/>
     27                         <xsl:call-template name="PartList"/>
     28                     </xsl:when>
     29                     <xsl:otherwise>
     30                         <div class="NoPart">
     31                             <xsl:text>无内容,请添加章节</xsl:text>
     32                         </div>
     33                     </xsl:otherwise>
     34                 </xsl:choose>
     35                 <!--this js must be here,if not be here,invalid in IE6\Opear\Chome-->
     36             
     37                 <div class="scroll">
     38                     <input name="scrollspeed" id="scrollspeed" title="Scroll Speed" onchange="javascript:setSpeed();" value="5"/>
     39                     <input name="bgcolor" id="bgcolor" value="#FEF7DA" tilte="Background Color"/>
     40                     <input name="fcolor" id="fcolor" value="#000000" tilte="Font Color"/>
     41                     <input name="Fsize" id="Fsize" value="16pt" tilte="Font Size"/>
     42                     <input type="button" title="Save" value="Save" onclick="javascript:saveSet();"/>
     43                 </div>
     44 
     45                 <script src="Novel.js"/>
     46 
     47             </body>
     48         </html>
     49     </xsl:template>
     50     <xsl:template name="PartIndex">
     51         <div class="roundconner">
     52             <xsl:call-template name="Roundconner">
     53                 <xsl:with-param name="IsTop" select="''"/>
     54             </xsl:call-template>
     55             <div name="Content" id="Content" class="Content">
     56                 <table width="100%">
     57                     <tbody style="text-align : '.'">
     58                         <xsl:for-each select="/Article/Part">
     59                             <xsl:choose>
     60                                 <xsl:when test="position() mod 3=2">
     61                                     <xsl:call-template name="IndexGroup">
     62                                         <xsl:with-param name="th1">
     63                                             <xsl:value-of select="concat(position()-1,$SplitToken)"/>
     64                                             <xsl:value-of select="./preceding-sibling::*[position()=1]/@Index"/>
     65 
     66                                         </xsl:with-param>
     67                                         <xsl:with-param name="th2">
     68                                             <xsl:value-of select="concat(concat(position(),$SplitToken),@Index)"/>
     69                                         </xsl:with-param>
     70                                         <xsl:with-param name="th3">
     71                                             <xsl:value-of select="concat(position()+1,$SplitToken)"/>
     72                                             <xsl:value-of select="./following-sibling::*[position()=1]/@Index"/>
     73                                         </xsl:with-param>
     74                                     </xsl:call-template>
     75                                 </xsl:when>
     76                                 <xsl:when test="(position() mod 3=1) and (position()=last())">
     77                                     <xsl:call-template name="IndexGroup">
     78                                         <xsl:with-param name="th1">
     79                                             <xsl:value-of select="concat(concat(position(),$SplitToken),@Index)"/>
     80                                         </xsl:with-param>
     81                                     </xsl:call-template>
     82                                 </xsl:when>
     83                             </xsl:choose>
     84                         </xsl:for-each>
     85                     </tbody>
     86                 </table>
     87             </div>
     88             <xsl:call-template name="Roundconner">
     89                 <xsl:with-param name="IsTop" select="'1'"/>
     90             </xsl:call-template>
     91         </div>
     92     </xsl:template>
     93     <xsl:template name="IndexGroup">
     94         <xsl:param name="th1" select="''"/>
     95         <xsl:param name="th2" select="''"/>
     96         <xsl:param name="th3" select="''"/>
     97         <tr>
     98             <th>
     99                 <xsl:call-template name="AddLink">
    100                     <xsl:with-param name="str" select="$th1"/>
    101                 </xsl:call-template>
    102                 <xsl:if test="./preceding::*[position()=1]/@Volume">
    103                     <font class="Volume">
    104                         <xsl:call-template name="AddLink"/>&#160;&#160;[<xsl:value-of select="./preceding::*[position()=1]/@Volume"/>]
    105                     </font>
    106                 </xsl:if>
    107             </th>
    108             <th>
    109                 <xsl:call-template name="AddLink">
    110                     <xsl:with-param name="str" select="$th2"/>
    111                 </xsl:call-template>
    112                 <xsl:if test="./@Volume">
    113                     <font class="Volume">
    114                         <xsl:call-template name="AddLink"/>&#160;&#160;[<xsl:value-of select="./@Volume"/>]
    115                     </font>
    116                 </xsl:if>
    117             </th>
    118             <th>
    119                 <xsl:call-template name="AddLink">
    120                     <xsl:with-param name="str" select="$th3"/>
    121                 </xsl:call-template>
    122                 <xsl:if test="./following::*[position()=1]/@Volume">
    123                     <font class="Volume">
    124                         <xsl:call-template name="AddLink"/>&#160;&#160;[<xsl:value-of select="./following::*[position()=1]/@Volume"/>]
    125                     </font>
    126                 </xsl:if>
    127             </th>
    128         </tr>
    129     </xsl:template>
    130     <xsl:template name="AddLink">
    131         <xsl:param name="str" select="''"/>
    132         <a href="#{substring-before($str,$SplitToken)}">
    133             <xsl:value-of select="substring-after($str,$SplitToken)"/>
    134         </a>
    135     </xsl:template>
    136     <xsl:template name="PartTitle">
    137         <xsl:param name="name" select="''"/>
    138         <xsl:param name="pos">0</xsl:param>
    139         <div>
    140             <a class="PartIndex" name="{$pos}">
    141                 <xsl:value-of select="$name"/>
    142             </a>
    143             <xsl:if test="(count(/Article/*)>1)">
    144                 <font class="PartStep">
    145                     <a href="#{-1+$pos}">上章</a>
    146                     <a href="#{1+$pos}">下章</a>
    147                     <a href="#0">返回</a>
    148                 </font>
    149             </xsl:if>
    150         </div>
    151     </xsl:template>
    152     <xsl:template name="PartList">
    153         <div class="roundconner">
    154             <xsl:call-template name="Roundconner">
    155                 <xsl:with-param name="IsTop" select="''"/>
    156             </xsl:call-template>
    157             <xsl:for-each select="//Part">
    158                 <xsl:call-template name="PartTitle">
    159                     <xsl:with-param name="name" select="@Index"/>
    160                     <xsl:with-param name="pos" select="position()"/>
    161                 </xsl:call-template>
    162                 <div name="Content" id="Content" class="Content">
    163                     <!-- add img-->
    164                     <xsl:if test="(count(./img)>0)">
    165                         <div class="imgDiv" style="clear:both">
    166                             <xsl:for-each select="./img">
    167                                 <xsl:element name="img">
    168                                     <xsl:attribute name="src"><xsl:value-of select="@src"/></xsl:attribute>
    169                                 </xsl:element>
    170                             </xsl:for-each>
    171                         </div>
    172                     </xsl:if>
    173                     <xsl:call-template name="ChangeLine">
    174                         <xsl:with-param name="str">
    175                             <xsl:choose>
    176                                 <xsl:when test="contains(., $SplitToken)">
    177                                     <xsl:value-of select="substring-after(., $SplitToken)"/>
    178                                 </xsl:when>
    179                                 <xsl:otherwise>
    180                                     <xsl:value-of select="."/>
    181                                 </xsl:otherwise>
    182                             </xsl:choose>
    183                         </xsl:with-param>
    184                         <xsl:with-param name="pat">
    185                             <xsl:value-of select="$SplitToken"/>
    186                         </xsl:with-param>
    187                     </xsl:call-template>
    188                 </div>
    189                 <xsl:if test="(count(/Article/*)>1) and ( position()!=last())">
    190                     <div class="split"/>
    191                 </xsl:if>
    192             </xsl:for-each>
    193             <xsl:call-template name="Roundconner">
    194                 <xsl:with-param name="IsTop" select="bot"/>
    195             </xsl:call-template>
    196         </div>
    197     </xsl:template>
    198     <xsl:template name="ChangeLine">
    199         <xsl:param name="str"/>
    200         <xsl:param name="pat"/>
    201 &#12288;&#12288;
    202         <xsl:choose>
    203             <xsl:when test="contains($str, $pat)">
    204                 <xsl:if test="not(starts-with($str, $pat))">
    205                     <xsl:value-of select="substring-before($str, $pat)"/>
    206                     <br/>
    207                 </xsl:if>
    208                 <xsl:call-template name="ChangeLine">
    209                     <xsl:with-param name="str" select="substring-after($str, $pat)"/>
    210                     <xsl:with-param name="pat" select="$pat"/>
    211                 </xsl:call-template>
    212             </xsl:when>
    213             <xsl:otherwise>
    214                 <xsl:value-of select="$str"/>
    215             </xsl:otherwise>
    216         </xsl:choose>
    217     </xsl:template>
    218     <xsl:template name="Roundconner">
    219         <xsl:param name="IsTop" select="''"/>
    220         <xsl:choose>
    221             <xsl:when test="$IsTop=''">
    222                 <b class="rtop">
    223                     <b class="r1"/>
    224                     <b class="r2"/>
    225                     <b class="r3"/>
    226                     <b class="r4"/>
    227                 </b>
    228             </xsl:when>
    229             <xsl:otherwise>
    230                 <b class="rbottom">
    231                     <b class="r4"/>
    232                     <b class="r3"/>
    233                     <b class="r2"/>
    234                     <b class="r1"/>
    235                 </b>
    236             </xsl:otherwise>
    237         </xsl:choose>
    238     </xsl:template>
    239 </xsl:stylesheet>

    其中xslt中用到了一点javascript来实现对cookie的读取和自动滚屏功能,这里也给出对应的novel.js代码

      1 var curPos, timer,speed=5;
      2 ////////////
      3 var scrollspeed=document.getElementById("scrollspeed");
      4 var bgcolor=document.getElementById("bgcolor");
      5 var fcolor=document.getElementById("fcolor");
      6 var Fsize=document.getElementById("Fsize");
      7 
      8 function setCookies(cookieName,cookieValue, expirehours)
      9 {
     10   var today = new Date();
     11   var expire = new Date();
     12   expire.setTime(today.getTime() + 3600000 * 356 * 24);
     13   document.cookie = cookieName+'='+escape(cookieValue)+ ';expires='+expire.toGMTString();
     14 }
     15 function ReadCookies(cookieName,obj)
     16 {
     17     var theCookie=''+document.cookie;//alert(document.cookie);
     18     var ind=theCookie.indexOf(cookieName);
     19     if (ind==-1 || cookieName=='') return obj;
     20     var ind1=theCookie.indexOf(';',ind);
     21     if (ind1==-1) ind1=theCookie.length;//alert(ind+"\n"+ind1);
     22     return unescape(theCookie.substring(ind+cookieName.length+1,ind1));
     23 }
     24 function saveSet()
     25 {
     26     setCookies("scrollspeed",scrollspeed.value);
     27 
     28     setCookies("bgcolor",bgcolor.value);
     29     ChangeBgcolor(bgcolor.value);
     30 
     31     setCookies("fcolor",fcolor.value);
     32     ChangeFcolor(fcolor.value);
     33 
     34     setCookies("Fsize",Fsize.value);
     35     ChangeFsize(Fsize.value);
     36 
     37 }
     38 
     39 function Change(obj,index)
     40 {
     41     var oCB=document.getElementsByName('Content');
     42     for(i=0;i<oCB.length;i++)
     43     {
     44             oCB[i].style.backgroundColor=obj;
     45     }
     46 }
     47 function ChangeBgcolor(color)
     48 {
     49     var oCB=document.getElementsByName('Content');
     50     for(i=0;i<oCB.length;i++)
     51     {
     52             oCB[i].style.backgroundColor=color;
     53     }
     54 }
     55 function ChangeFcolor(color)
     56 {
     57     var oCB=document.getElementsByName('Content');
     58 
     59     for(i=0;i<oCB.length;i++)
     60     {
     61 
     62             oCB[i].style.color=color;
     63     }
     64 }
     65 function ChangeFsize(fontSize)
     66 {
     67     var oCB=document.getElementsByName('Content');
     68 
     69     for(i=0;i<oCB.length;i++)
     70     {
     71             oCB[i].style.fontSize =fontSize;
     72     }
     73 }
     74 function loadSet()
     75 {
     76     scrollspeed.value=ReadCookies("scrollspeed",5);
     77     setSpeed();
     78 
     79     bgcolor.value=ReadCookies("bgcolor","#FFFFFF");;
     80     ChangeBgcolor(bgcolor.value);
     81 
     82 
     83     fcolor.value=ReadCookies("fcolor","#000000");;
     84     ChangeFcolor(fcolor.value);
     85 
     86 
     87     Fsize.value=ReadCookies("Fsize","16px");;
     88     ChangeFsize(Fsize.value);
     89 }
     90 
     91 //document.oncontextmenu = new Function("return false;");
     92 //双击鼠标滚动屏幕的代码
     93 //var curPos, timer,speed=5;
     94 function initialize(){timer=setInterval ("scrollwindow()",300/speed);}
     95 function sc(){clearInterval(timer);}
     96 function scrollwindow(){
     97     curPos=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop;
     98     window.scroll(0,++curPos);
     99     var sTop=document.body.scrollTop?document.body.scrollTop:document.documentElement.scrollTop;
    100     if (curPos !=sTop) sc();
    101 }
    102 function setSpeed(){
    103 
    104     speed = parseInt(scrollspeed.value);
    105 
    106 };
    107 document.onmousedown = sc;
    108 document.ondblclick = initialize;
    109 loadSet();

     另外。xslt也使用到了css,这里提供css文件的源码

      1 .scroll{width:70px;float:right;
      2 position:fixed !important; top/**/:200px;
      3 position:absolute; z-index:100; top:expression(offsetParent.scrollTop+200);right:4px;}
      4 input{
      5 width:99%;
      6 border :1px solid #999999;
      7 font-weight:bold;
      8 background:transparent ;
      9 color:red;
     10 height:21px;
     11 font-size:10t;
     12 }
     13 body,b.rtop, b.rbottom,div.split{
     14 background: #4E3F3A;  /*url(back.gif);*/
     15 }
     16 div.roundconner,b.rtop b, b.rbottom b,div.Content,.NoPart{
     17 /*改变圆角矩形的背景色*/
     18 background:#FEF7DA;
     19 }
     20 *{
     21 font:             100.0% "宋体","Trebuchet MS", "Verdana", "Arial", "sans-serif";
     22 color:            #000000;
     23 }
     24 body {
     25 /*line-height : 180%;*/
     26 text-align:center;
     27 }
     28 div
     29 {
     30 /*firefox中,必须加入以下两句才能让div在body中居中显示*/
     31 margin-left:auto;
     32 margin-right:auto;
     33 }
     34 div.Content{
     35 line-height : 180%;
     36 font-size:14pt;
     37 }
     38 div.split{
     39 height:20px;
     40 }
     41 .title{
     42 color:white;
     43 font-size:16pt;
     44 }
     45 table{
     46 border-collapse:collapse ;
     47 }
     48 .roundconner {
     49 width:90%;
     50 text-align:left;
     51 
     52 }
     53 b.rtop, b.rbottom {
     54 display:    block;
     55 
     56 }
     57 b.rtop b, b.rbottom b {
     58 display:    block;
     59 height:     1px;
     60 overflow:   hidden;
     61 
     62 }
     63 b.r1 {
     64 margin: 0 5px;
     65 }
     66 b.r2 {
     67 margin: 0 3px;
     68 }
     69 b.r3 {
     70 margin: 0 2px;
     71 }
     72 b.rtop b.r4, b.rbottom b.r4 {
     73 margin: 0 1px;
     74 height: 2px;
     75 }
     76 a{
     77 text-decoration : none;
     78 }
     79 a:hover {
     80 color : red;
     81 }
     82 .imgDiv{
     83 text-align:center;
     84 width:98%;
     85 }
     86 th{
     87 background:transparent ;
     88 font-size:11pt;
     89 font-weight : normal;
     90 text-align : left;
     91 padding-left:8px;
     92 width:33%;
     93 }
     94 br{
     95 text-indent: 2em;
     96 }
     97 .Volume{
     98 font-weight:bold;
     99 font-size:9pt;
    100 }
    101 .PartIndex, .PartStep ,.PartStep a{
    102 
    103 background-color:#E8E2CC;
    104 /*border :1px solid #CDCDDC;*/
    105 font-size:10pt;
    106 font-weight:bold;
    107 height:21px;
    108 vertical-align : center;
    109 line-height:21px;
    110 }
    111 .PartIndex{
    112 text-align : left;
    113 float:left;
    114 width:86%;
    115 }
    116 .PartStep{
    117 text-align : right;
    118 float:right;
    119 width:14%;
    120 }
    121 .NoPart{
    122 height:200px;
    123 vertical-align : center;
    124 line-height:200px;
    125 font-size:36pt;
    126 }

    现在我们手头上有了如下文件

    1.盘龙.xml         小说文件
    2.Article.xslt     xml样式表文件
    3.Article.xsd      xml的结构定义文件,对最终显示无影响
    4.novel.js         读取和设置本机cookie,和提供自动滚屏功能
    5.UI.css           

    以上文件放置在同一个目录,双击盘龙.xml ,浏览器中就可以查看到小说内容

    其实有了xml格式的章节内容,我们可以轻易的实现各种转化器,将xml格式转成txt,umd等等格式,并且可以以rss的形式发布小说内容。

    这个留待以后在实现。

  • 相关阅读:
    XML导入数据库
    文件流 +Excel导出
    LINQ
    Lambda
    多线程编程
    反射
    匿名类
    匿名类
    委托与事件
    ubuntu开放指定端口
  • 原文地址:https://www.cnblogs.com/simfe/p/2789586.html
Copyright © 2011-2022 走看看