1.程序需求
在NAS上(可以理解为局域网上一个存放了若干文件的IP地址),有若干个DBF文件,它们占用的空间都不大。现在要做一个功能,就是把这些文件每隔一段时间,做一个快照,以XML形式保存DBF文件的值。并把XML文档保存到指定位置,用已经写好的XSLT样式表,来显示这个XML文件,并提供一些XML文件的统计信息。
2.我的架构
DbfMonitor(程序根目录) | |-dbfs(目录) | | | |-dbf1(目录) | | |-dbf1.dbf | |-dbf2(目录) | | |-dbf2.dbf | ... | |-xmls(目录) | | | |-xml1(目录) | | |-xml1.xml | | |-xml1.xslt | | |-xml1.css(xslt文件调用) | |-xml2(目录) | | |-xml2.xml | | |-xml2.xslt | | |-xml2.css(xslt文件调用) | ... | |-Dbf2Xml.exe(一个VB.NET程序,将DBF转换到XML) |-DbfMonitor.bat(单击这个文件运行程序) |-DbfMonitor.vbs
关于这个程序结构树的说明如下:
1)双击DbfMonitor.bat文件,启动这个程序,DbfMonitor.bat会调用文件DbfMonitor.vbs
2)DbfMonitor.vbs有两个功能:其一为每隔一段时间,将NAS上(或其他任意Windows文件系统可访问到的位置)的DBF文件,同步到本地dbfs目录下;其二为调用程序Dbf2Xml,把DBF文件的内容写到指定的XML文件中,保存到xmls目录下对应的目录中
3)生成XML文件,会引用与之同名的*.xslt文件作为样式表,*.xslt中带有javascript代码,保证每隔一段时间XML文件会刷新一次,用来保证查看到的是最新的DBF文件内容,*.xslt文件还会调用同名的css样式表,用来保证一些界面的美观
3.部分程序代码
1)DbfMonitor.bat
@cscript DbfMonitor.vbs @pause
2)DbfMonitor.vbs
下面的程序,以同步一个A.DBF到A.XML为例:
Option Explicit WScript.Echo "DBF同步显示工具 2015年2月 Tsybius" WScript.Echo "--------------------------------" Dim FSO : Set FSO = WScript.CreateObject("Scripting.FileSystemObject") Dim WS : Set WS = WScript.CreateObject("WScript.Shell") '这里设定时间间隔信息 Const Interval = 10000 Dim CurHour Dim CurMinute Dim CurSecond Do '打印时间信息 CurHour = Hour(Now) CurMinute = Minute(Now) CurSecond = Second(Now) WScript.Echo "当前时间: " & CurHour & "时 " & CurMinute & "分 " & CurSecond & "秒" 'A.DBF WScript.Echo "复制文件A.DBF" If FSO.FileExists("P:\A.DBF") Then FSO.CopyFile "P:\A.DBF","dbfs\dbf_A\A.dbf",True WScript.Echo "A.DBF文件复制完毕: dbfs\dbf_A\A.dbf" WS.Run "Dbf2Xml.exe dbfs\dbf_A\A.dbf xmls\xml_A\A.xml A MS_VFP_Oledb",0 Else WScript.Echo "未找到A.DBF" End If WScript.Sleep(Interval) Loop
3)Dbf2Xml.exe
这是一个用VB.NET语言写的DBF转XML工具
它可以把DBF转换成下面形式的XML文件:
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type='text/xsl' href='A.xslt'?> <DATA COUNT="32" INPUT-DBF="A.dbf" OUTPUT-XML="A.xml"> <DATA_ROW> <列1>列1内容</列1> <列2>列2内容</列2> 列3、列4 ... </DATA_ROW> <DATA_ROW> <列1>列1内容</列1> <列2>列2内容</列2> 列3、列4 ... </DATA_ROW> 行3、行4 ... </DATA>
这个程序是在一个另一个程序的基础上改写的:http://www.oschina.net/p/curtia_dbf2xml
共有4个参数,分别是DBF文件地址、转换后的XML文件地址、针对该XML转换需要添加的参数(这个参数是在程序中根据实际情况进行改动的)、连接DBF文件使用的连接方式(有多种连接方式时可以配置它)
4)关于xslt文件
对于每一个XML,都要有一个自己专属的XSLT文件与之匹配,这样才能让XML文件显示出想要的东西
下面是一个XML文件示例:A.xml
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet type='text/xsl' href='A.xslt'?> <DATA COUNT="3" INPUT-DBF="A.dbf" OUTPUT-XML="A.xml"> <DATA_ROW> <COLUMN1>A</COLUMN1> <COLUMN2>1</COLUMN2> <COLUMN3>1</COLUMN3> <COLUMN4>1</COLUMN4> <COLUMN5>1</COLUMN5> <COLUMN6>1</COLUMN6> <COLUMN7>1</COLUMN7> </DATA_ROW> <DATA_ROW> <COLUMN1>B</COLUMN1> <COLUMN2>3</COLUMN2> <COLUMN3>3</COLUMN3> <COLUMN4>3</COLUMN4> <COLUMN5>3</COLUMN5> <COLUMN6>3</COLUMN6> <COLUMN7>3</COLUMN7> </DATA_ROW> <DATA_ROW> <COLUMN1>C</COLUMN1> <COLUMN2>2</COLUMN2> <COLUMN3>2</COLUMN3> <COLUMN4>2</COLUMN4> <COLUMN5>2</COLUMN5> <COLUMN6>2</COLUMN6> <COLUMN7>2</COLUMN7> </DATA_ROW> </DATA>
它对应的XSLT文件的示例为:A.xslt
<?xml version="1.0" encoding="gb2312"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html"/> <xsl:template match="/"> <html> <head> <Meta content="zh-cn" http-equiv="Content-Language"/> <Meta content="text/html; charset=utf-16" http-equiv="Content-Type"/> <link type="text/css" rel="stylesheet" href="A.css"/> <title>标题</title> <script type="text/javascript" language="javascript"> <xsl:text disable-output-escaping="yes"> <![CDATA[ function myrefresh() { window.location.reload(); } setTimeout('myrefresh()',300000); //在这里指定刷新间隔,单位毫秒 ]]> </xsl:text> </script> </head> <body> <div id="content"> <br /> 数据总计: <strong><font color="red"><xsl:value-of select="DATA/@COUNT" /></font></strong><br /> 输入文件: <strong><font color="red"><xsl:value-of select="DATA/@INPUT-DBF" /></font></strong><br /> 输出文件: <strong><font color="red"><xsl:value-of select="DATA/@OUTPUT-XML" /></font></strong><br /> <hr /> <xsl:variable name="A_1" select="count(DATA/DATA_ROW[COLUMN1='A' and COLUMN2='1'])"/> <xsl:variable name="A_2" select="count(DATA/DATA_ROW[COLUMN1='A' and COLUMN2='2'])"/> <xsl:variable name="A_3" select="count(DATA/DATA_ROW[COLUMN1='A' and COLUMN2='3'])"/> <xsl:variable name="A_4" select="count(DATA/DATA_ROW[COLUMN1='A' and COLUMN2='4'])"/> <xsl:variable name="A_5" select="count(DATA/DATA_ROW[COLUMN1='A' and COLUMN2='5'])"/> <xsl:variable name="B_1" select="count(DATA/DATA_ROW[COLUMN1='B' and COLUMN2='1'])"/> <xsl:variable name="B_2" select="count(DATA/DATA_ROW[COLUMN1='B' and COLUMN2='2'])"/> <xsl:variable name="B_3" select="count(DATA/DATA_ROW[COLUMN1='B' and COLUMN2='3'])"/> <xsl:variable name="B_4" select="count(DATA/DATA_ROW[COLUMN1='B' and COLUMN2='4'])"/> <xsl:variable name="B_5" select="count(DATA/DATA_ROW[COLUMN1='B' and COLUMN2='5'])"/> <xsl:variable name="C_1" select="count(DATA/DATA_ROW[COLUMN1='C' and COLUMN2='1'])"/> <xsl:variable name="C_2" select="count(DATA/DATA_ROW[COLUMN1='C' and COLUMN2='2'])"/> <xsl:variable name="C_3" select="count(DATA/DATA_ROW[COLUMN1='C' and COLUMN2='3'])"/> <xsl:variable name="C_4" select="count(DATA/DATA_ROW[COLUMN1='C' and COLUMN2='4'])"/> <xsl:variable name="C_5" select="count(DATA/DATA_ROW[COLUMN1='C' and COLUMN2='5'])"/> 统计信息:<br /> <table> <tr> <th></th> <th>1</th> <th>2</th> <th>3</th> <th>4</th> <th>5</th> </tr> <tr> <td>A</td> <td><xsl:value-of select="$A_1"/></td> <td><xsl:value-of select="$A_2"/></td> <td><xsl:value-of select="$A_3"/></td> <td><xsl:value-of select="$A_4"/></td> <td><xsl:value-of select="$A_5"/></td> </tr> <tr> <td>B+C</td> <td><xsl:value-of select="$B_1+$C_1"/></td> <td><xsl:value-of select="$B_2+$C_2"/></td> <td><xsl:value-of select="$B_3+$C_3"/></td> <td><xsl:value-of select="$B_4+$C_4"/></td> <td><xsl:value-of select="$B_5+$C_5"/></td> </tr> </table> <hr /> <table> <tr> <th>列1</th> <th>列2</th> <th>列3</th> <th>列4</th> <th>列5</th> <th>列6</th> <th>列7</th> </tr> <xsl:for-each select="DATA/DATA_ROW"> <tr> <td class="textCentered"><xsl:value-of select="COLUMN1"/></td> <td class="textCentered"><xsl:value-of select="COLUMN2"/></td> <td class="textCentered"><xsl:value-of select="COLUMN3"/></td> <td class="textCentered"><xsl:value-of select="COLUMN4"/></td> <td class="textCentered"><xsl:value-of select="COLUMN5"/></td> <td class="textCentered"><xsl:value-of select="COLUMN6"/></td> <td class="textCentered"><xsl:value-of select="COLUMN7"/></td> </tr> </xsl:for-each> </table> </div> </body> </html> </xsl:template> </xsl:stylesheet>
/* Body style,for the entire document */ body { background: #F3F3F4; color: #1E1E1F; font-family: "Segoe UI",Tahoma,Geneva,Verdana,sans-serif; padding: 0; margin: 0; } /* Header1 style,used for the main title */ h1 { padding: 10px 0px 10px 10px; font-size: 21pt; background-color: #E2E2E2; border-bottom: 1px #C1C1C2 solid; color: #201F20; margin: 0; font-weight: normal; } /* Table styles */ table { border-spacing: 0 0; border-collapse: collapse; font-size: 10pt; } table th { background: #3399FF; text-align: center; text-decoration: none; font-weight: normal; padding: 3px 6px 3px 6px; width:100px; } table td { vertical-align: top; text-align: center; padding: 3px 6px 5px 5px; margin: 0px; border: 1px solid #E7E7E8; background: #66FF33; } .textCentered { text-align: center; } #content { padding: 0px 12px 40px 40px; }
最终A.xml打开后的效果为:
4.其他注意事项
1)IE浏览器在加载XML时,会提示“为了有利于保护安全性,Internet Explorer已限制此网页运行可以访问计算机的脚本或ActiveX控件。请单击这里获取选项...”,在鼠标右键弹出的菜单中选择“允许阻止的内容”,即可调用javascript代码不断刷新页面
2)Windows的文件系统无法直接通过IP地址获取NAS上的文件,必须要对网络驱动器做完映射后才能通过新赋予的盘符访问NAS上的路径,方法是在桌面上的计算机图标上,单击鼠标右键→映射网络驱动器。如果不进行驱动器映射,在访问时会报错,比如在cmd中使用cd命令访问路径“\\IP地址\目录名\”,会提示“CMD不支持将UNC路径作为当前目录”
3)如果不小心直接点击了*.vbs文件,要关闭它,需要先按下“Ctrl+Alt+Delete”,进入Windows 任务管理器,在进程选项卡中关闭进程wscript.exe
END