DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 動態 XForms 提交
動態 XForms 提交
編輯:XML詳解     

 本文示例源代碼或素材下載

  背景

  我們往往需要單獨設計一個表單,以便從多個不同的來源收集標准數據集。單獨一個全能的表單非常適合特定的數據采集要求,因為可以約束數據的輸入值,保證數據完整性,而且也很容易對比和匯總不同來源的數據。對於這類數據驅動的表單,XForms 是一種很好的選擇,因為它是一種可以在多種支持 Web 的平台上運行的開放標准。

  為了采集數據,XForms 文檔必須有多個提交目標,或者輸入完成後用戶點擊提交按鈕時數據需要發送到或者保存到的位置。但是,每個表單填寫位置可能有特殊的提交需求,比如保存提交表單的本地副本、提交表單到只讀的位置或者記錄下每次提交的 “vault”,以便進行審計或記錄日志。這些特殊的提交需求可能降低表單的價值,因為單個表單不能封裝各表單填寫位置的特殊提交需求。通過使用 JavaScript for Document Object Model(DOM)編程,運行時即可在浏覽器將提交目標與 XForms 文檔聯系起來,從而將提交需求與標准表單分離開來,這樣每個表單填寫處可以有任意多個特殊的提交目標。

  本文中使用的完整 XForms 文檔、模式、XML 數據實例和樣式表可以參見 下載 部分。

  示例 XForms 文檔

  假設有一個長期醫療研究項目,參與者定期會晤,交流一些可能遇到的症狀。為定期會診記錄病例症狀的簡單表單如 圖 1 中的 XForms 文檔所示。

  圖 1. XForms 表示的簡單病理報告動態 XForms 提交

  這個簡單的例子中只有三個輸入字段:Subject ID 字符串、xs:date 類型的日期(使用 XForms 呈現的日期選擇器限制輸入的值)和枚舉類型的症狀(無、發燒、肌肉疼痛、關節僵硬、惡心)。該 XForms 文檔提交實例的模式定義如 清單 1 所示。

清單 1. 症狀報告模式...      
<xs:simpleType name="incidentType">
 <xs:restriction base="xs:string">
  <xs:enumeration value="none" />   
  <xs:enumeration value="fever" />
  <xs:enumeration value="muscle pain" />
  <xs:enumeration value="joint stiffness" />
  <xs:enumeration value="nausea" />        
 </xs:restriction>
</xs:simpleType>
<xs:complexType name="incidentReportType">
  <xs:sequence>
    <xs:element name="theSubjectID" type="xs:string" maxOccurs="1" />
    <xs:element name="theDate" type="xs:date" maxOccurs="1" />
    <xs:element name="theSymptom" type="incidentType" maxOccurs="1" />
  </xs:sequence>
</xs:complexType>
<xs:element name="theIncident" type="incidentReportType"/>
...

  因為每個字段背後都有一個模式定義明確規定了類型,除非所有數據都對模式有效,否則 XForms 可能會禁止提交輸入數據,以確保所有提交點上數據的同質性。該模式中,theDate 被定義為 xs:date 類型,theSymptom 則定義為 incidentType 類型。此外,maxOccurs 屬性進一步限制在提交的數據實例中每個輸入字段只能有一個。清單 2 給出了該表單提交實例的一個例子。

 清單 2. XML 實例...   
<theIncident xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="theIncident.xsd">
     <theSubjectID>7D</theSubjectID>
     <theDate>2006-10-13</theDate>
     <theSymptom>none</theSymptom>
</theIncident> 
...  

  靜態 XForms 提交

  圖 1 中的 XForms 表單有一個提交按鈕,用戶在輸入完成後可以提交表單。這個提交按鈕的激活可以和 XForms 數據模型專用的提交動作結合起來。該例中的數據模型是根據 清單 1 模式定義的一個如 清單 2 所示的實例。在 XForms 文檔中,這個提交動作(可以是多個)和應用的模型與實例一起定義。比如,清單 3 中定義了兩個提交:remoteSave 提交將把 XML 實例 theIncidentInstance 提交給 xformstest.org 回顯服務,localSave 則在本地磁盤上保存 theIncidentInstance 的副本。

  清單 3. 包含提交定義的 XForms 模型定義...
<xforms:model id="theIncidentModel" schema="theIncident.xsd">
 <xforms:instance id="theIncidentInstance" src="theIncident.XML"/>
 <xforms:submission id="remoteSave"
 action="http://xformstest.org/CGI-bin/showinstance.sh"
   method="post"/>
 <xforms:submission id="localSave" action="./local_save.XML"
   method="put"/>               
</xforms:model>
...


 

使用一個簡單的 XForms 觸發器創建一個提交按鈕,激活的時候調用兩個(還可以更多)提交動作,如 清單 4 所示。

  清單 4. 提交按鈕的觸發器...    
<xforms:trigger>
<xforms:label>Submit</xforms:label>  
  <xforms:action ev:event="DOMactivate">
    <xforms:send submission="remoteSave"/>
    <xforms:send submission="localSave"/>
  </xforms:action>
</xforms:trigger>
...    

  這是一個有效的表單,但要求表單作者知道表單填寫者的本地提交需求(像本地磁盤保存一樣),對於在多個地點使用的表單這種方法不容易改變。需要一種辦法允許當地的表單填寫者能夠獨立於表單和提交實例定義本地提交需求。

  動態 XForms 提交

  XForms 數據模型機制和用於文檔對象模型(DOM)的 JavaScript 編程提供了一種可伸縮的解決方案,不需要修改表單,但是允許每個提交點靈活定義任意多個特殊的提交需求。這種解決方案的第一部分是定義和包含提交動作的單獨的數據模型,XForms 很容易做到。可制訂一個簡單的模式來保存提交動作信息,比如提交的目標、惟一標識提交動作的標識符和調用方法(如 put 或 post),如 清單 5 所示。

  清單 5. 提交動作模式...      
<xs:simpleType name="methodType">
 <xs:restriction base="xs:string">
   <xs:enumeration value="put" />
     <xs:enumeration value="post" />
      </xs:restriction>
</xs:simpleType>
<xs:complexType name="actionType">
 <xs:simpleContent>
     <xs:extension base="xs:string">
 <xs:attribute name="theMethod" type="methodType" />
 <xs:attribute name="theId" type="xs:string" />                  
      </xs:extension>
    </xs:simpleContent>
  </xs:complexType>
     
<xs:complexType name="submitListType" >
  <xs:sequenceminOccurs="0"maxOccurs="unbounded">
  <xs:element name="theAction" type="actionType" />
 </xs:sequence>
</xs:complexType>
...              


 

該模式將允許創建使用多重提交填充單獨數據模型的實例。可以發送包含默認提交設置的基本數據模型然後在每個站點上進行編輯。清單 3 所示 “硬編碼” XForms 文檔中包含兩個提交選項的那個具體例子,可用作 清單 6 所示的 XForms 數據模型。

  清單 6. 提交動作實例...   
<theSubmitList>
  <theAction theMethod="post" theId="remoteSave">
  http://xformstest.org/CGI-bin/showinstance.s</theAction>
  <theAction theMethod="put" theId="localSave">./local_save.XML</theAction>
</theSubmitList>   
...

  有了獨立的提交數據模型之後,就可以使用 Javascript 編寫 DOM 代碼在運行的時候把要提交的實例模型和本地提交目標聯系起來。JavaScript 代碼和包含“空”觸發器的兩個模型如 清單 7 所示。要注意,theIncidentModel 不再像 清單 3 所示的靜態、硬編碼提交模型那樣包含提交定義。

  清單 7. 動態 XForms 提交的 JavaScript 代碼...
  <xforms:model id="theSubmitModel" schema="theSubmits.xsd">
    <xforms:instance id="theSubmitInstance" src="theSubmits.XML"/>
  </xforms:model>
  
  <xforms:model id="theIncidentModel" schema="theIncident.xsd">
   <xforms:instance id="theIncidentInstance" src="theIncident.XML"/>
  </xforms:model>
  <script type="">
  function buildSubmits()
  {
   var oModel = document.getElementById("theSubmitModel");
   var oInstance = oModel.getInstanceDocument("theSubmitInstance");
   var pModel = document.getElementById("theIncidentModel");
   var pInstance = pModel.getInstanceDocument("theIncidentInstance");
  
   var theSubmits = oInstance.getElementsByTagName("theSubmits");
   var theSubmitList = theSubmits[0].getElementsByTagName("theSubmitList");
   var theAction = theSubmitList[0].getElementsByTagName("theAction");
     var submitTrigger = document.getElementById("dynamicSubmit");
   for(var i = 0; i < theAction.length ;i++) {
  n = document.createElementNS("http://www.w3.org/2002/xforms", "xforms:submission");
  n.setAttribute("id" , theAction[i].getAttribute("theId"));
  n.setAttribute("method" , theAction[i].getAttribute("theMethod"));    
  n.setAttribute("action" , theAction[i].textContent);
  pModel.appendChild(n);
  m = document.createElementNS("http://www.w3.org/2002/xforms", "xforms:send");
   m.setAttribute("submission" , theAction[i].getAttribute("theId")) ;
    submitTrigger.appendChild(m);
   }
  }
  </script>  
...
  <xforms:trigger>
    <xforms:label>Submit</xforms:label>  
    <xforms:action ev:event="DOMactivate" id="dynamicSubmit">
    </xforms:action>
  </xforms:trigger>
  
   <script type="">
    buildSubmits();
   </script> 
...

對應兩個 XForms 數據模型,JavaScript 建立了兩個模型和實例變量,即 theSubmitModel 和 theIncidentModel,然後遍歷 theSubmitModel 實例,在 DOM 中向 theIncidentModel 實例的 XForms 模型定義增加提交,向 XForms 提交按鈕觸發器增加提交動作。要修改的觸發器必須惟一標識,這裡觸發器用 ID dynamicSubmit 惟一地標識它。這些修改都在 DOM 內存中完成,永遠不會寫到磁盤上的 XForms 代碼本身之中,但是可以用 DOM Inspector 在 DOM 中觀察到,如 圖 2 所示。

  動態 XForms 提交

  圖 2. DOM 中顯示的動態提交動態 XForms 提交

  提交編輯的表單

  由於提交保存在單獨的數據模型和磁盤文件中,這個單獨的提交實例都成為其自身的 XForms 文檔的候選項,後者很容易從 XML 實例中生成並使用 XML Forms Generator(XML Forms Generator Eclipse 插件的鏈接請參閱 參考資料部分)建立自己的模式。得到的 XForms 文檔如 圖 3 所示。

  圖 3. 提交編輯 XForms動態 XForms 提交

  結束語

  如果需要創建數據驅動的、能夠對 XML 實例數據提交應用模式驅動約束的、從多個需要迅速進行關聯和匯總的不同來源采集同質數據的表單,XForms 無疑是一種極其出色的可選技術。通過將表單填寫方站點的獨特數據提交需求與邏輯表單本身和提交的實例分離開來,即可控制一個表單和一組數據輸入約束,提供了多重、特定於站點的靈活提交選擇。要將表單 DOM 和多重、特定於站點的提交需求相分離,然後再在運行時連接起來,可通過 JavaScript 編程完成,即在 DOM 中,從單獨的模型讀取多個提交選項,並將這些選項寫入 XForms 提交的實例模型和 XForms 提交按鈕觸發器。

  XForms 1.0 需要以 DOM 為依據使用 JavaScript 編程,來支持這種動態的多重提交目標場合,不過制定 XForms 1.1 工作草案的 W3C XForms 工作組正在考慮一種聲明性解決方案。具體來說,就是為 XForms submission 增加一個 resource 子元素,允許用它所包含的 URI 來根據實例數據動態計算提交。


 

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved