DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> Thinking XML: Firefox 3.0 和 XML
Thinking XML: Firefox 3.0 和 XML
編輯:XML詳解     

 對於目前存在的成百上千個 XML 處理工具,Web 浏覽器仍然是操作的中心 — XML 開發人員十分幸運,操作似乎永遠不會減慢。過去的幾年裡,我撰寫了關於開發人員喜愛的 Firefox 浏覽器中與 XML 相關的特性的一系列文章;我已經從 Firefox 1.5 介紹到了 2.0。最近,Firefox 升級到 3.0 版,其中有很多全面改進以及大量用於 XML 處理的新的出色開發。許多改進都來自核心 Web 處理引擎 Gecko 從 1.8.1 到 1.9 的升級。

  3.0 版中的 XML 基本原理

  常用縮寫詞

  CSS:層疊樣式表(Cascading Style Sheet)

  DOM:文檔對象模型(Document Object Model)

  DTD:文檔類型定義(Document Type Definition)

  Html:超文本標記語言(HyperText Markup Language)

  SVG:可伸縮矢量圖形(Scalable Vector Graphics)

  URI:統一資源標識符(Uniform Resource IdentifIEr)

  URL:統一資源定位符(Uniform Resource Locator)

  W3C:萬維網聯盟(World Wide Web Consortium)

  XSLT:可擴展樣式表轉換(Extensible Stylesheet Transformation)

  XML:可擴展標記語言(Extensible Markup Language)

  XML 領域包含大量技術,但是全部內容的起點都是解析器;Firefox 3 引入了對基本 XML 解析的一項巨大改進。在過去的 Mozilla 浏覽器中,解析 XML 文檔是同步的,將阻止對文檔執行的所有操作,直至完全載入該文檔。對比 XML 解析與 Html 解析,後者一直都是異步的,這樣文檔的各個部分在解析後就可以使用了。對於用戶,這意味著他將開始看到在浏覽器處理完頁面之前 Web 頁面是如何形成的;另一方面,使用 XML 文檔,在完成解析前,用戶根本看不到任何內容。這是一個可用性問題,不利於處理大型的 XML 文檔。

在 Firefox 3.0 中,XML 內容模型是逐步構造的,類似於 Html。這將使 XML 在 Web 上的實際應用產生重大變化。有一些例外 — 最明顯的是 XSLT 不是逐步處理的。理論上,您可以使用 XPath 的有限子集,逐步應用 XSLT 的子集,但是這樣做本身就需要花費巨大精力,並且超出 Firefox 3.0 的范圍。

  我曾經希望 Firefox 3.0 中的改進之一是提供 xml:id 支持。關於是否支持 XML:id 曾存在一些爭議,但是如果可以出現在將來的發行版中,那麼就可以使用一個補丁。一般而言,Firefox JavaScript 為在 XML 文檔中使用 getElementById 而提供的惟一方法是內部 DTD 子集(無外部子集,並且沒有 xml:id)。如果確實需要 XML:id,請從 JavaScript 中使用 XPath 查詢 XML 名稱空間和 “id” 本地名稱中的屬性。

  未能實現的另一個期望的核心改進是允許用戶請求浏覽器裝入外部 DTD 子集。看上去好像補丁程序已就緒,但是沒有足夠可用的開發人員資源完成 Q&A 過程,因此未能在 Firefox 3.0 發行版中實現。

  XSLT 的重大改進

  希望在 Firefox 中使用 XSLT 的人們獲得的最大勝利是支持 EXSLT,這是一組由 XSLT 社區開發和支持的 XSLT 擴展,並且受到許多其他 XSLT 處理器的支持。Firefox 3.0 添加了對於大型 EXSLT 子集的支持,首先從 node-set 函數開始,這是解決 XSLT 1.0 中最嚴重的限制的重要方法。EXSLT 被組織到各個模塊中,每個模塊都定義若干個擴展函數和元素。Firefox 3.0 在一組模塊中實現了一組擴展,如下所示:

  Common:Firefox 3.0 實現了通用函數的基本集合:

  exsl:node-set 允許您將結果樹片段轉換為節點集,這樣便可以對其應用 XPath。


exsl:object-type 是一個內省工具,用於報告對象類型,例如字符串、節點集、數字或者布爾值。

  Sets:Firefox 3.0 實現了一些使用節點集的有用擴展:

  set:difference 將計算兩個集合之間的差異,返回一個節點集,該節點集的節點位於其中一個實參,而不在其他實參中。

  set:distinct 將檢驗節點集以查找擁有相同字符串值的節點,並且只保留每個節點的一個實例,而將其余都刪除。

  如果返回的節點集中的節點在兩個集合中都有,則 set:intersection 將計算交集。

  set:has-same-node 將確定兩個節點集是否有任何公共節點(例如,它們是不是共享實際的同一個節點,而不只是具有相同字符串值的不同節點,與 XPath = 運算符一樣)。

  set:leading 將返回一個節點集,其中的節點按照文檔順序要比另一個節點集中的第一個節點早出現。

  set:trailing 將返回一個節點集,其中的節點按照文檔順序要比另一個節點集中的第一個節點晚出現。

  Strings:Firefox 3.0 實現了一些使用字符串的有用擴展:

  str:concat 將返回一個字符串,它見集合中每個節點的字符串值連接在一起(與內置的 concat 函數相比,該擴展將連接固定順序的表達式)。

  str:split 將使用一種模式把一個字符串分隔為一連串子字符串(使用在運行時構造的節點集表示)。

  str:tokenize 將使用一組單字符標記把一個字符串分隔為一連串子字符串(使用在運行時構造的節點集表示)。

  Math:Firefox 3.0 實現了一些函數,這些函數可以讓您更輕松地從節點集內容中獲取最小數值量和最大數值量:

  math:max 將返回給定節點集中的內容的最高數值。

  math:min 將返回給定節點集中的內容的最低數值。

math:highest 將返回內容中擁有最高數值的節點集。

  math:lowest 將返回內容中擁有最低數值的節點集。

  正則表達式:Firefox 3.0 將正則表達式的功能引入到 XSLT 中:

  regexp:match 將在運行時構造節點集時,針對字符串匹配正則表達式模式並返回匹配的子字符串。

  regexp:test 將檢查字符串是否與正則表達式模式完全匹配。

  regexp:replace 將替代匹配正則表達式模式的子字符串。

  通過示例了解 EXSLT

  為了幫助您開始在轉換過程中使用 EXSLT,我構造了一個示例,並在其中實踐了大量在 Firefox 3.0 中實現的函數。我發現在浏覽器中使用 XSLT 的最佳實踐之一是交付針對半結構化數據的報告。您將用戶引導向包含處理指令的 XML 文件,應用 XSLT 轉換。在這種情況下,通常可以規定所需的浏覽器版本,因此無需過於擔心跨浏覽器兼容性問題。此外,還將服務器的大量工作分擔到每個用戶的計算機中。清單 1(employees.XML)是一個員工信息文件,我將針對該文件在 Firefox 3.0 中呈現一個報告。


清單 1. 員工信息文件 employees.XML

<?XML version="1.0" encoding="utf-8"?> 
<?xml-stylesheet type="text/XML" href="employees.xsl"?> 
<employees> 
 <department id="res"> 
  <title>Research</title> 
  <info>http://example.com/ar-and-dee for more info</info> 
  <employee id="111"> 
   <title>Coordinator</title> 
   <name> 
    <given>Rene</given> 
    <family>Descartes</family> 
   </name> 
   <location building="PAR1">France</location> 
  </employee> 
  <employee id="112"> 
   <title>Project Manager</title> 
   <name> 
    <given>Abu Ja'far</given> 
    <family>Al Kwarizmi</family> 
   </name> 
   <location building="BAG2">Iraq</location> 
  </employee> 
 </department> 
 <department id="exec"> 
  <title>Executive</title> 
  <info>Home of the head honchos</info> 
  <employee id="101"> 
   <title>ChIEf Executive Officer</title> 
   <name> 
    <given>Genghis</given> 
    <family>Khan</family> 
    <honorific>The Great</honorific> 
   </name> 
   <location building="MON1">China</location> 
  </employee> 
 </department> 
 <department id="hr"> 
  <title>Human Resources</title> 
  <info>We're happy to serve you at http://example.com/hr</info> 
  <employee id="102"> 
   <title>Manager of Wellness</title> 
   <name> 
    <given>Ching-Yuen</given> 
    <family>Li</family> 
   </name> 
   <location building="SZE1">China</location> 
  </employee> 
 </department> 
</employees> 


 

注意,位於頂部的 XML-stylesheet 處理指令將指示浏覽器使用 XSLT。清單 2(employees.xsl)是從 清單 1 生成報告的轉換。


清單 2. 通過員工信息文件(employees.xsl)生成報告的轉換

<?XML version="1.0" encoding="utf-8"?> 
<!-- A --> 
<xsl:transform version="1.0" 
 XMLns:xsl="http://www.w3.org/1999/XSL/Transform" 
 XMLns:math="http://exslt.org/math" 
 XMLns:regex="http://exslt.org/regular-expressions" 
 XMLns:set="http://exslt.org/sets" 
 XMLns:str="http://exslt.org/strings" 
 XMLns="http://www.w3.org/1999/xHtml" 
 exclude-result-prefixes="set math regex str"> 
 <!-- Notice the namespace declarations for EXSLT. 
    Notice also exclude-result-prefixes, since you don't want those 
    namespace declarations in the result XHtml 
  --> 
 
 <!-- Use XML mode to approximate XHtml output 
    (notice the doc type declaration info) --> 
 <xsl:output method="XML" encoding="utf-8" 
       doctype-public="-//W3C//DTD XHtml 1.1//EN" 
       doctype-system="http://www.w3.org/TR/xhtml11/DTD/xHtml11.dtd"/> 
 
 <xsl:template match="employees"> 
  <!-- Put the presentation style into a separate file, 
     specifIEd using a processing instruction in the output --> 
  <xsl:processing-instruction name="XML-stylesheet"> 
   <xsl:text>type="text/css" href="employees.CSS"</xsl:text> 
  </xsl:processing-instruction> 
  <Html XML:lang="en"> 
   <head> 
    <title>Employee report</title> 
   </head> 
   <body> 
    <h1>Employee report</h1> 
    <table> 
     <xsl:apply-templates/> 
    </table> 
    <hr/> 
    <xsl:call-template name="stats"/> 
   </body> 
  </Html> 
 </xsl:template> 
 
 <xsl:template name="stats"> 
  <xsl:variable name="execs" 
   select="department[title='Executive']/employee"/> 
  <xsl:variable name="employees-in-china" 
   select="department/employee[location='China']"/> 
  <!-- Use set:has-same-node to check whether the two separate 
     XPath querIEs have any node sets in common --> 
  <xsl:if test="set:has-same-node($execs, $employees-in-china)"> 
   <p>Note: At least one executive presently works in China</p> 
  </xsl:if> 
  <dl> 
   <dt>CountrIEs where employees presently work</dt> 
   <dd> 
    <!-- Use set:distinct to eliminate duplicate country names 
       from the query result --> 
    <xsl:for-each select="set:distinct(department/employee/location)"> 
     <xsl:value-of select="."/> 
     <xsl:if test="not(position()=last())"> 
      <xsl:text>, </xsl:text> 
     </xsl:if> 
    </xsl:for-each> 
   </dd> 
   <dt>Newest employee</dt> 
   <!-- Use math:highest to determine the highest numerical value of employee ID --> 
   <dd><xsl:value-of select="math:highest(department/employee/@id)"/></dd> 
  </dl> 
 </xsl:template> 
 
 <xsl:template match="department"> 
  <tr> 
   <td colspan="4"> 
    <!-- Use regular expressions to sniff out URLs from unstructured content --> 
    <!-- [1] ensues that if multiple URLs are detected, only the first is used --> 
    <a href="{regex:match(info, 'http://[a-zA-Z0-9-_/\.]*', '')[1]}"> 
     <xsl:value-of select="title"/> 
    </a> 
   </td> 
  </tr> 
  <xsl:apply-templates select="employee"/> 
 </xsl:template> 
 
 <xsl:template match="employee"> 
  <tr> 
   <td> 
    <xsl:value-of select="name/given"/> 
    <xsl:text> </xsl:text> 
    <xsl:value-of select="name/family"/> 
   </td> 
   <td> 
    <!-- Use str:concat to construct a composite ID from ancestor --> 
    <!-- If, for example you added an id attribute to the root element, 
       the value would be appended for each employee --> 
    <xsl:value-of select="str:concat(ancestor-or-self::*/@id)"/> 
   </td> 
   <td> 
    <xsl:value-of select="title"/> 
   </td> 
   <td> 
    <!-- Standard concat assembles a string from a fixed sequence of expressions --> 
    <xsl:value-of select="concat(location, '(', location/@building, ')')"/> 
   </td> 
  </tr> 
 </xsl:template> 
 
</xsl:transform> 

我在代碼中加了很多注釋,突出說明了使用 EXSLT 的位置,以及其他有用注釋。生成的輸出將引用一個 CSS 樣式表,主要用來演示這種模式。清單 3(employees.css)顯示了 CSS。


清單 3. 通過員工信息文件(employees.CSS)生成的報告的演示樣式表

body { background-color: lightblue; } 
td { padding-left: 1em; } 

  將 清單 1 裝載到 Firefox 3.0 中可以獲得圖 1 中的顯示。


圖 1. 使用清單 1-3 生成的報告的 Firefox 3.0 顯示
Thinking XML: Firefox 3.0 和 XML

  結束語

  除了主要的解析改進以及 EXSLT 之外,Firefox 3.0 還修正了在使用帶有名稱空間的 XML 文檔時遇到的遵從性問題。DOMAttrModifIEd 事件現在將正確處理名稱空間中的屬性,並且,對於元素在標記名中使用名稱空間前綴的子樹,Javascript DOM 方法 getElementsByTagName() 現在也可以正確處理。有許多 CSS 和 JavaScript 補丁,可以幫助簡化 XML 開發人員的工作。

  可伸縮向量圖形(Scalable Vector Graphics,SVG)是所有人都喜歡的 XML 技術,對於這種技術的用戶,Firefox 3.0 甚至提供了更多優點。它現在支持模式和掩碼(mask),讓您可以實現更豐富的效果;支持全部 SVG 1.1 過濾器。您現在可以向任何一個舊 Web 浏覽器對象應用 SVG 轉換,例如,這樣您可以決定將 IFRAME 旋轉 45 度,而這通常需要使用 Canvas 工具。Mozilla 團隊已經提供了 SVG DOM 支持,同時還修復了大量 bug。

  有些人會說,XML 並未在 Web 上獲得預料的成功,但是有一點可以肯定的是,您已經可以在浏覽器中用 XML 完成很多事情,並且得益於 Web 浏覽器中的持續開發,每年都會出現新的 XML 特性。Firefox 3.0 是一個重要的裡程碑,它實現了對 XML 處理的核心性能改進,以及對 XSLT、DOM 和 SVG 的增強。您不會在嘗試使用這些新功能時出錯。即使由於跨浏覽器需要而不能立即使用所有新功能,隨著 Web 應用程序的不斷發展,您也要做好應對未來的准備。

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





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