跳轉到內容

XSLTForms/轉換函式

來自 Wikibooks,開放世界中的開放書籍

transform() 函式是 XSLTForms 對標準 XForms 函式庫的擴充套件。公開討論表明它是基於對 類似函式 的提議,該函式將被包含在 XForms 2.0 中,但工作似乎在 2011 年陷入停滯。在 XPath 表示式模組 的當前草案中似乎沒有 transform() 函式,目前也沒有為 transform() 函式單獨模組的活動規範。

語法/簽名

[編輯 | 編輯原始碼]

transform() 函式將外部 XSLT 樣式表應用於節點集。在當前版本的 XSLTForms(大約從 2014 年開始)中,它接受三個或更多引數。

  • 第一個引數是要轉換的節點(例如 instance('foo')/bar/baz 或只是 child-element.)。
  • 第二個引數要麼是
    • 作為字串的 XSLT 樣式表的 URI(例如 'my-transform.xsl'),要麼是
    • XSLT 樣式表的字串表示。
  • 第三個引數如果是字串形式的 XSLT 樣式表,則為 true,如果是 XSLT 樣式表的 URI,則為 false
  • 如果存在,第四、六、八... 個引數是 XSLT 樣式表引數的名稱。
  • 如果存在,第五、七、九... 個引數是這些引數的值。

注意:早期版本的函式只接受兩個引數:要轉換的節點和 XSLT 樣式表的 URI。

transform() 函式返回一個字串。這對許多 XSLT 使用者來說似乎不太可能,因此需要強調:transform() 函式返回一個字串。

  • 如果 XSLT 輸出方法是 text,則返回值是字串(在幾乎所有瀏覽器中,在幾乎所有情況下,都包裝在某種瀏覽器相關的 XML 元素中)。
  • 如果 XSLT 輸出方法是 xml,則返回值是生成的 XML 文件的序列化形式。在大多數情況下,檢視它將顯示尖括號和與號作為 <& 進行轉義。但是,如果返回值被注入到 XHTML 文件中,則結果將像普通的 HTML 一樣格式化。

(那麼 html 輸出方法呢?)

示例和用法

[編輯 | 編輯原始碼]

以只讀形式格式化資料

[編輯 | 編輯原始碼]

transform() 的一個用途是將 XML 例項資料格式化為適當地格式化的 HTML,以便瀏覽器以方便的只讀方式顯示。例如

  <div style="margin: 1em 0;">
    <xf:output value="transform(my-tricky-element, 'display-tricky.xsl')"
               mediatype="application/xhtml+xml" />
  </div>

顯示 XML 原始碼

[編輯 | 編輯原始碼]

transform() 的另一個用途是美化 XML 例項資料,以便瀏覽器以方便的只讀方式顯示 XML 原始碼。例如

  <h2>XML representation of the data</h2>

  <pre style="border: 2px #552211 solid; 
              padding: 0.5em; 
              background-color: #f7eed4;">
    <xf:output value="transform(instance('doc'),'../lib/prettyprint.xsl')" 
               mediatype="text/plain" />
  </pre>

此示例假設一個美化樣式表,該樣式表會生成帶有換行符和適當縮排的輸出。這在原則上不是必需的(可以使用 serialize(instance('user-data')) 代替),但在實踐中很有用,因為否則一些瀏覽器會在一行很長的輸出中顯示整個 XML 文件。

更新例項

[編輯 | 編輯原始碼]

由於 transform() 返回一個字串,因此以下嘗試為 XForms 生成新的文件例項以便進一步處理將失敗:它不會用轉換的輸出替換例項 foo,而是用轉換結果的序列化字串形式替換 foo內容

  <xf:trigger>
    <xf:label>Generate diagram</xf:label>
    <xf:action ev:event="DOMActivate">
      <xf:setvalue ref="instance('svg')" 
                   value="transform(instance('input'),'make-svg.xsl')"/>
      <xf:toggle case="picture"/>
    </xf:action>
  </xf:trigger>

如果 svg 例項最初包含一個正常的 SVG 文件,那麼在觸發顯示的觸發器後,它將包含一個 SVG 元素,該元素包含 XML 轉義的 SVG 文件作為一個單獨的文字節點。

  <svg xmlns="http://www.w3.org/2000/svg" 
       width="100%" 
       height="100%">&lt;svg xmlns="http://www.w3.org/2000/svg" 
           xmlns:svg="http://www.w3.org/2000/svg" 
           width="900" 
           height="1000"&gt;
  &lt;desc&gt;SVG representation of the data&lt;/desc&gt;
  ...
  &lt;/svg&gt;</svg>

解決此問題的一種方法是使用實驗性動作 xf:setnode 以及 innerouter 屬性,以替換節點的內容或節點本身。

  <xf:trigger>
    <xf:label>Inner</xf:label>
    <xf:setnode ref="." ev:event="DOMActivate"
               inner="'&lt;item&gt;b&lt;/item&gt;'"/>
  </xf:trigger>
  <xf:trigger>
    <xf:label>Outer</xf:label>
    <xf:setnode ref="item" ev:event="DOMActivate"
               outer="'&lt;item&gt;c&lt;/item&gt;'"/>
  </xf:trigger>

另一種解決方法是將字串提交到伺服器上的指令碼,該指令碼將它作為 XML 回顯。(參見 關於 setnode 操作的討論 中的示例)。

已知問題和故障

[編輯 | 編輯原始碼]

在 Safari 中,以及在較舊版本的 Chrome 中(直到版本 30,甚至可能更晚),如果在 transform() 的第二個引數中給出的樣式表包含 xsl:import 指令,則轉換可能會失敗。症狀是一個錯誤警報,提示 TypeError: null is not an object (evaluating 'resultDocument.documentElement')。(如果樣式表包含 xsl:include 指令,則也可能會出現此問題,但尚未得到驗證。)此問題不會出現在 Firefox、Opera 或更新版本的 Chrome 中(從版本 49 開始,甚至可能更早)。

解決方法:刪除 xsl:import,以便樣式表成為一個獨立的物件,不依賴於其他樣式表。


更多資訊

[編輯 | 編輯原始碼]

可以從 一組 transform() 測試用例 中收集到一些進一步的資訊,這些測試用例說明了呼叫函式的各種不同方法,並顯示了在每種情況下它產生的結果。

華夏公益教科書