使用XML+XSLT實現業務表單

http://www.cnblogs.com/lijun4017/archive/2008/04/28/1175323.html

其實這是我的一個兩年前的項目中用到的東西,今天剛好翻以前的代碼,看到,覺得也是自己想出來的東西,寫寫也無妨,哪怕是爲了填充我空虛的blog。這個是一個智能客戶端,但是裏面涉及的表單非常之多,統計一下,有200個張。本來也不是問題,用FORM一個一個畫也能夠畫出來,但是這樣有幾個缺點,一方面導致智能客戶端的dll變的比較大,每次更新的時候,都要下載整個dll;一方面分工不好分,原來那個公司那時候只有我用過winform,老闆就把這個任務分配給我了。但是我一個人,要做那麼多的表單,而且在比較短的時間內,也不是說不可能,太累了。我想想看能不能有其他方法。

當時XFORM的概念相當熱,我也看了一些資料,覺得還是不太成熟,沒有敢用。

後來看了微軟office2007中的infopath,感覺功能非常強,它可以實現用infopath設計表單,然後用表單控件把表單嵌入到winform中去,並且可以實現表單中的數據加載和保存功能。但是唯一的遺憾就是如果要使用它,就必須要客戶機器上安裝office2007,這樣就不太現實了。

最後來想到的是用xml+xslt是動態生成靜態頁面,然後把靜態頁面嵌入在winform的瀏覽器控件裏面,並且屏蔽一些瀏覽器控件的一些屬性,看起來就和winform設計的表單差不多了。這樣就方便多了,我可以叫美工幫我設計表單,叫其他的asp.net的程序員幫忙做XML和XSLT以及裏面的javascript腳本。後來的項目進展說明了,這種方式真的大大的提高了工作效率,也讓我輕鬆了不少,嘿嘿,又偷懶了。


下面我說說具體的過程吧。
1。首先我在設計表的時候,把整個表單的內容設計成XML類型的字段,當然,其他需要搜索的字段還是要單獨建字段,並且保存xslt文件的版本號。
2。設計表單的XML結構,下面是示例。

<?xml version="1.0" encoding="utf-8" ?>
<!--現場會議記錄-->
<meetnote>
  
<enterprise></enterprise>
  
<!--會議名稱-->
  
<meets>
    
<meet>
      
<name>meet1</name>
      
<checked>false</checked>
    
</meet>
    
<meet>
      
<name>meet2</name>
      
<checked>false</checked>
    
</meet>
    
<meet>
      
<name>meet3</name>
      
<checked>false</checked>
    
</meet>
  
</meets>
  
<compere />
  
<recorder />
  
<address />
  
<meetdate />
  
<content />
</meetnote>


3.設計表單的XSLT文件,下面是示例。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
                xmlns:msxsl
="urn:schemas-microsoft-com:xslt"                 
                version
="1.0" >
  
<xsl:template match="/">
    
<html>
      
<head>
        
<link href="../css/xmltable.css" rel="stylesheet" type="text/css" />
        
<script language="javascript">
          
//使用客戶端日期JS腳本初始化

          var date 
= new Date();
          var   Fun_Year 
= date.getYear();
          var   Fun_Month 
= date.getMonth()+1;
          var   Fun_Day 
= date.getDate();
        
</script>
        
<script language="javascript" src="../javascript/calendar.js"></script>
        
<script language="javascript" src="../javascript/check.js"></script>
        
<script language="javascript" src="../javascript/common.js"></script>
        
<script language="javascript">
          function validate()
          
{
          var errorinfo
="";
          
if(clearSpace(txtcompere.value)=="")
          
{
          errorinfo 
+= "主持人爲空\n";
          }

          
if(clearSpace(txtaddress.value)=="")
          
{
          errorinfo
+= "會議地點爲空\n";
          }

          
if(clearSpace(txtrecorder.value)=="")
          
{
          errorinfo
+="記錄人爲空\n";
          }

          
if(clearSpace(txtmeetdate.value)=="")
          
{
          errorinfo 
+= "會議時間爲空\n";
          }

          
if(clearSpace(txtcontent.innerText)=="")
          
{
          errorinfo
+= "會議內容爲空\n";
          }

          
//會議名稱
          if(txtmeet1.checked != true &amp;&amp; txtmeet2.checked != true &amp;&amp; txtmeet3.checked != true)
          
{
          errorinfo
+= "請選擇會議名稱\n";
          }

          
if(errorinfo=="")
          
{
          
return true;
          }

          
else
          
{
          window.external.ShowErrorMessage(errorinfo);
          
return false;
          }


          }

          
//數據保存
          function savetoxml()
          
{
          var doc 
= new ActiveXObject("Msxml2.DOMDocument");
          doc.async 
= false;
          
//調用c#方法獲取xml文件路徑
          var xmlfilepath = window.external.GetXMLPathForJava();
          doc.load(xmlfilepath);

          
//會議名稱
          doc.selectNodes("meetnote/meets/meet")[0].lastChild.text=(txtmeet1.checked==0)?'false':'true';
          doc.selectNodes(
"meetnote/meets/meet")[1].lastChild.text=(txtmeet2.checked==0)?'false':'true';
          doc.selectNodes(
"meetnote/meets/meet")[2].lastChild.text=(txtmeet3.checked==0)?'false':'true';

          doc.selectSingleNode(
"meetnote/compere").text=txtcompere.value;
          doc.selectSingleNode(
"meetnote/recorder").text=txtrecorder.value;
          doc.selectSingleNode(
"meetnote/address").text=txtaddress.value;
          doc.selectSingleNode(
"meetnote/meetdate").text=txtmeetdate.value;
          doc.selectSingleNode(
"meetnote/content").text=txtcontent.innerText;

          
//調用c#方法保存xml文件
          var examfiletype = window.external.GetExamFileType();
          var examfilename 
= window.external.GetExamFileName();
          window.external.Save(doc.xml,examfiletype,examfilename);
          
return true;
          }

        
</script>
        
</head>
      
<body>
        
<xsl:apply-templates/>
      
</body>
    
</html>
  
</xsl:template>

  
<xsl:template match="meetnote">
   
    
<table border="1" align="center" cellPadding="0" cellSpacing="0"  class="table">

      
<tr>
        
<td  class="td1"  colspan="4">
          
<div align="center" class="title">現場審覈會議記錄</div>
        
</td>
      
</tr>
      
<tr>
        
<td class="td2">
          
<span>受審覈方:</span>

          
<xsl:value-of select="enterprise" />

        
</td>
      
</tr>
      
<tr>
        
<td class="td2">
          
<span>會議名稱:</span>
          
<xsl:apply-templates select="meets/meet"/>
        
</td>
      
</tr>
      
<tr>
        
<td class="td2">
          
<span>主 持 人:</span>
          
<input style="WIDTH: 150px; " type="text" name="txtcompere">
            
<xsl:attribute name="value">
              
<xsl:value-of select="compere" />
            
</xsl:attribute>
          
</input>
          
<span>會議地點:</span>
          
<input style="WIDTH: 200px; " type="text" name="txtaddress">
            
<xsl:attribute name="value">
              
<xsl:value-of select="address" />
            
</xsl:attribute>
          
</input>
        
</td>
      
</tr>
      
<tr>
        
<td class="td2">
          
<span>記 錄 人:</span>
          
<input style="WIDTH: 150px; " type="text" name="txtrecorder">
            
<xsl:attribute name="value">
              
<xsl:value-of select="recorder" />
            
</xsl:attribute>
          
</input>
          
<span>會議時間:</span>
          
<input style="WIDTH: 100px; " type="text" name="txtmeetdate" onfocus="calendar();" id="txtmeetdate">
            
<xsl:attribute name="value">
              
<xsl:value-of select="meetdate" />
            
</xsl:attribute>
          
</input>
        
</td>
      
</tr>
      
<tr>
        
<td   valign="top" class="td2">
          
<span>會議內容:</span>
          
<br/>
          
<textarea style="WIDTH: 100%;HEIGHT:150px " type="text" name="txtcontent">
              
<xsl:value-of select="content" />
          
</textarea>
        
</td>
      
</tr>
    
</table>
  
</xsl:template>
  
<!--會議名稱-->
  
<xsl:template match="meets/meet">
    
<xsl:if test="name='meet1'">
      
<input type="checkbox" name="txtmeet1" id="txtmeet1" onclick="radiobutton(this,'txtmeet')">
        
<xsl:if test="checked='true'">
          
<xsl:attribute name="checked">
            
checked
          
</xsl:attribute>
        
</xsl:if>
      
</input>
      
<span>首次會議</span>
    
</xsl:if>
    
<xsl:if test="name='meet2'">
      
<input type="checkbox" name="txtmeet2" id="txtmeet2" onclick="radiobutton(this,'txtmeet')">
        
<xsl:if test="checked='true'">
          
<xsl:attribute name="checked">
            
checked
          
</xsl:attribute>
        
</xsl:if>
      
</input>
      
<span>溝通會議</span>
    
</xsl:if>
    
<xsl:if test="name='meet3'">
      
<input type="checkbox" name="txtmeet3" id="txtmeet3" onclick="radiobutton(this,'txtmeet')">
        
<xsl:if test="checked='true'">
          
<xsl:attribute name="checked">
            
checked
          
</xsl:attribute>
        
</xsl:if>
      
</input>
      
<span>末次會議</span>
    
</xsl:if>
  
</xsl:template>
</xsl:stylesheet>



4。在XSLT文件中加入JS腳本,用戶驗證用戶輸入,收集表單數據,加載表單數據等。(這裏涉及到JS代碼和瀏覽器控件所在的winform窗體的代碼的相互調用。)
1)首先把winform窗體的類加上這個屬性[ComVisible(true)]

2) 在winform窗體裏面寫上public的方法

        //取得xml文件路徑(供javascript調用)
        public string GetXMLPathForJava()
        {          
            return tempxmlfilepath;
        }
3)在XSLT文件裏面的JS代碼中調用這個方法
  //調用c#方法獲取xml文件路徑
         var xmlfilepath = window.external.GetXMLPathForJava();
4)在XSLT文件中定義JS方法
         //數據保存
          function savetoxml()
          {
         } 
5)在winform窗體中調用JS方法
 //調用JS方法
 Object result = webBrowser1.Document.InvokeScript("savetoxml");

5.在顯示頁面的時候,我先使用下面的代碼把XSLT和XML轉換成HTML文件,存放在臨時文件夾中,然後把瀏覽器控件的URL指向它。

  XslCompiledTransform transForm = new XslCompiledTransform();
            
string xsltemplatepath = TemplateHelper.GetFactoryFormXSLTemplatePath(m_FileType, m_DataRow.xsl_version);

            
try
            
{
                transForm.Load(xsltemplatepath);
                transForm.Transform(tempxmlfilepath, temphtmlfilepath);
            }

            
catch(Exception ex)
            
{
                LogError.Write(ex.Message 
+ "\n" + ex.StackTrace);
                MessageBox.Show(
"模板文件加載出錯!");
                
this.Close();
                
return;
            }

            webBrowser1.Navigate(temphtmlfilepath);


6。在用戶點擊保存的時候,我通過XSLT中定義的JS代碼,直接把用戶保存的數據以XML的方式返回給winform的代碼,然後保存到數據庫中去。

 Object validateresult = webBrowser1.Document.InvokeScript("validate");
            
if (Convert.ToBoolean(validateresult) == true)
            
{
                Object result 
= webBrowser1.Document.InvokeScript("savetoxml");
                
if (Convert.ToBoolean(result) == true)
                
{
                    
this.Close();
                }

                
else
                
{
                    MessageBox.Show(
"保存出錯""提示", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                    
this.DialogResult = DialogResult.None;
                }

            }

            
else
            
{
                
this.DialogResult = DialogResult.None;
            }


7。刪除剛纔產生的臨時文件。


 

發佈了57 篇原創文章 · 獲贊 7 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章