DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> XML學習教程 >> XML詳解 >> 用XSLT 2.0生成SQL
用XSLT 2.0生成SQL
編輯:XML詳解     

假定您是一名新的 PHP 項目的工程團隊主管,並且要求必備的條件都已滿足,初步的數據模型包括大約 150 個表。現在該考慮一下進度表了。估計您每天能編寫一個數據庫訪問類並完成其單元測試,因此,150 個表要用 150 天的時間。假設每個月工作 20 天,是不是要用將近八個月的時間來編寫數據庫訪問層?

  這樣做可能不行,需要有一種方法來縮短所需的時間。您可以使用持久性框架,但即使這種框架能夠把時間減半,仍然還需要四個月的時間。您還可以編寫通用的類庫,但是這樣的庫使用起來復雜不說,而且還非常容易出錯,難以調試。

  也可以編寫一兩個示例類,然後使用代碼生成器建立其他的類。在最糟糕的情況下,編寫生成器本身就可能要用一個月的時間。但是此後,所有代碼的生成只要花費幾分鐘的時間。此外,由於 SQL 架構與數據庫訪問代碼不匹配造成的缺陷也可以完全避免,因為 SQL 架構和訪問代碼都是由生成器建立的。

  這樣的計劃可行嗎?當然,本文就告訴您如何做,並說明為何應用程序更加容易維護,更加健壯,並且編寫起來更順手。本系列有兩篇文章,第 1 部分先介紹代碼生成的基礎,然後討論構建生成器的一部分,為給定的模型創建 SQL。第 2 部分將深入 XSL,通過遍歷創建 PHP 的代碼來說明如何完成生成器。

  代碼生成基礎

  首先,我們需要一個生成器,它接受數據庫的抽象模型並建立 SQL 架構和 PHP 數據庫訪問類。圖 1 給出了這種模型,並顯示了為其他技術(如 Java™ 代碼)生成數據庫代碼的可能性。

  圖 1. 生成器的基本信息流

用XSLT 2.0生成SQL


 

圖 1 中的虛線框(SQL 模型和數據庫訪問模型)表示從抽象模型創建的臨時模型。點線框(Java)表示另一種可能模型。

  下一個問題是采用何種技術。您可以使用 Java 代碼、Perl、Python 或 Ruby 編寫生成器。因為這項任務比較簡單,也可以用 Velocity 或 XSLT 這樣的模板引擎來實現該任務。XSLT 2.0 這樣的模板引擎就是一個很好的起點,它不僅本身具有強大的功能,而且還可以嵌入到 Java 代碼中進一步擴展。

  XSLT 2.0

  XSLT 2.0 為尋求代碼生成模板引擎的開發人員提供了廣泛的語言能力。本文就利用這些特性構建一個健壯的生成器,從抽象的表定義生成 SQL 和 PHP。在 XSLT 1.x 中只能使用單層轉換,但是在 XSLT 2.0 中可以建立將要生成代碼的中間模型。這一功能使理解和維護生成器更加容易,而且可以將生成器重定位到其他目標語言。

  作為一種 XML 轉換技術,XSLT 可以將 XML 轉換到其他 XML 或者文本。我們的這個代碼生成器項目中同時用到了這兩個工具,其中的 XSLT 2.0 對 XSLT 1.x 作了很多改進,本文將使用標准第二版中的三個新特性:

  函數:現在可以自定義函數。對 XSLT 第一版而言,這是一個重大的改進,第一版中使用的模板語法太羅嗦。

  中間樹:XSLT 的第一個版本只能對輸入的 XML 樹進行操作。XSLT 2.0 可以在內存中建立中間樹,然後用它派生出其他模板。

  結果文檔:現在單個模板可以生成多個輸出文件。我利用該特性生成 SQL 文件和單獨的 PHP 文件。

  下面將說明如何構建生成器。

  構建生成器

  首先從生成器的輸入開始,清單 1 為一個簡單的圖書數據庫提供了表定義的例子。

  清單 1. 輸入的抽象表定義

<?XML version="1.0" encoding="UTF-8"?>
<tables>
  <table name="Author">
    <fIEld name="first" type="text"/>
    <fIEld name="last" type="text"/>
  </table>
  <table name="Publisher">
    <fIEld name="name" type="text"/>
    <fIEld name="last" type="text"/>
  </table>
  <table name="Book">
    <fIEld name="name" type="text"/>
    <fIEld name="author" type="id"/>
    <fIEld name="publisher" type="id"/>
  </table>
</tables>

這段簡單的 XML 腳本定義了三個數據庫表及其字段:Author(作者)、Publisher(出版商)和 Book(圖書)。整個 PHP 應用程序的輸入要大得多,可能也復雜得多,但是作為起點來說,這段代碼挺合適。

  您可以創建一個生成器一次性地將這些 XML 轉化成 SQL 和 PHP,但是我不建議這樣做。這樣模板會變得非常復雜而難以維護。目前代碼生成的最佳實踐是采用多級模型,每一級都朝目標前進一步。與 Web 服務器中使用多層降低復雜性增強重用性一樣,這樣做降低了一次轉換的復雜性。

  回頭看一看 圖 1,就會發現抽象模型為 SQL 生成了一個模型,又通過數據庫訪問模型為 PHP 生成了另一個模型。這些模型都保存在中間樹中,然後用於建立代碼。圖 2 畫出了在生成器中轉化的 Author 表。

  圖 2. 單個 SQL 表的演化

用XSLT 2.0生成SQL

  圖 2 中最上方的方框顯示了原來的抽象表模型。中間的方框則是從抽象模型構建的 SQL 模型。最下面的方框顯示了最後的 SQL 輸出。可以看到,SQL 模型詳細規定了什麼將出現在最終的 SQL 文件中。代碼模板的任務就是將 XML 轉化成 SQL,從而能夠從單一的模型為不同數據庫生成代碼。現在來看一看 XSL。

  生成 SQL

  清單 2 顯示了生成器項目中主 XSL 樣式表的第一部分。

  清單 2. 主生成器 XSL 樣式表的開頭部分

<?XML version="1.0" encoding="UTF-8"?>
<xsl:stylesheet XMLns:xsl="http://www.w3.org/1999/XSL/Transform"
XMLns:gen="http://www.codegeneration.Net/" version="2.0">
  <!-- Output specifications -->
  <xsl:output method="text"/>
  <xsl:output method="xml" name="debug-XML" indent="yes"/>
  <xsl:output method="text" name="sql" indent="yes"/>
  <!-- SQL Templates -->
  <xsl:include href="gen2-sql.xsl" />
  <xsl:include href="gen2-sql-model.xsl" />
  <xsl:include href="gen2-querIEs.xsl" />
  <!-- Database Access Templates -->
  <xsl:include href="gen2-dba.xsl" />
  <xsl:include href="gen2-PHP.xsl" />
  <!-- The generator main entry point -->
  <xsl:template match="/">
    <!-- Create the SQL model -->
<xsl:text>Building SQL model
</xsl:text>
    <xsl:variable name="sql-model">
      <xsl:call-template name="gen-sql-model">
        <xsl:with-param name="model" select="."/>
      </xsl:call-template>
    </xsl:variable>
    
    <!-- Dump it out for debugging -->
<xsl:text>Dumping SQL model
</xsl:text>
    <xsl:result-document href="db/gen-tables.xml" format="debug-XML">
      <xsl:copy-of select="$sql-model"/>
    </xsl:result-document>
    <!-- Generate the SQL from the SQL model -->
<xsl:text>Generating SQL
</xsl:text>
    <xsl:result-document href="db/gen-tables.sql" format="sql" >
      <xsl:apply-templates mode="sql" select="$sql-model/sql" />
    <xsl:result-document>

腳本中最重要的部分就是創建 sql-model 變量的地方,該變量將保存 SQL 模型;另一個最重要部分是 result-document 標簽,它使用 sql-model 變量的內容創建 SQL 文件。這些標簽顯示了 XSLT 2.0 的兩個有價值的改進:使用 xsl:variable 標簽創建中間樹,使用 xsl:result-document 標簽創建多個輸出文件。

  現在來看看從抽象表模型生成 SQL 模型的模板。清單 3 顯示了 gen-sql-model 模板。

  清單 3. SQL 模型生成器

<?XML version="1.0" encoding="UTF-8"?>
<xsl:stylesheet XMLns:xsl="http://www.w3.org/1999/XSL/Transform"
  XMLns:gen="http://www.codegeneration.Net/" version="2.0">
  
  <!-- Builds the SQL model from the original data model -->
  <xsl:template name="gen-sql-model">
    <xsl:param name="model"/>
    <sql>
      <xsl:for-each select="$model/tables/table">
        <create name="{lower-case(@name)}"
  primary-key="{concat(lower-case(@name),'_id')}">
          <fIEld name="{concat(lower-case(@name),'_id')}"
  type="{gen:model-type-to-sql('integer')}"/>
          <xsl:for-each select="fIEld">
            <fIEld name="{lower-case(@name)}"
  type="{gen:model-type-to-sql(@type)}"/>
          </xsl:for-each>
        </create>
      </xsl:for-each>
    </sql>
  </xsl:template>
</xsl:stylesheet>


 

這個模板相當簡單:接受源模型並為 SQL 模型添加一些新的標簽。注意 gen:model-type-to-sql 函數的調用。調用的不是標准 XSLT 函數,而是清單 4 中所示的自定義函數。

  清單 4. model-to-SQL-type 轉換函數

  <xsl:function name="gen:model-type-to-sql">
    <xsl:param name="type"/>
    <xsl:choose>
      <xsl:when test="$type eq 'text'">TEXT NOT NULL</xsl:when>
      <xsl:when test="$type eq 'id'">INTEGER NOT NULL</xsl:when>
      <xsl:when test="$type eq 'integer'">INTEGER NOT NULL</xsl:when>
    </xsl:choose>
  </xsl:function>

  創建新的 XPath 函數的能力是 XSLT 2.0 的新增功能。在以前,只能使用 xsl:call-template 語法,隨著參數的增加可能變得非常麻煩。使用模板作為函數也破壞了模板名稱空間。

  生成 SQL 的最後一步是將 SQL 模型格式化為 SQL。可以使用清單 5 中所示的兩個模板。

  清單 5. SQL 生成模板

  <!-- Template for SQL create tags -->
  <xsl:template match="create" mode="sql">
DROP TABLE IF EXISTS <xsl:value-of select="@name" />;
CREATE <xsl:value-of select="@name" /> (
<xsl:apply-templates mode="sql" select="fIEld" />
PRIMARY KEY ( <xsl:value-of select="@primary-key" /> )
    );
  </xsl:template>
  <!-- Template for SQL fIEld tags -->
  <xsl:template match="fIEld" mode="sql">
<xsl:value-of select="concat(@name,' ',@type,',')" /><xsl:text>
</xsl:text>
  </xsl:template>

  這些就是所有真正需要采用的模板。我有一個與 SQL 模型中的 create 標簽相對應的模板。該模板使用 apply-templates 標簽處理其子標簽,這些標簽是用第二個模板格式化的。

  回顧一下 圖 2,要注意 XML 結構和 SQL 結構的相似性。create 標簽包含幾個字段標簽。與 SQL 類似,create 命令也包含幾個字段參數。按照與代碼相同的方式構造模型可以極大地簡化代碼模板。

  結束語

  本文介紹了 XSLT 2.0 中的一些新特性,即擴展的語言特性和為所要生成的代碼構建中間模型的能力,並示范了如何利用這些特性建立健壯的生成器,從抽象的表模型生成 SQL。

  第 2 部分將說明如何生成代碼的 PHP 部分,從而為 Web 服務器提供數據庫訪問,還將介紹 XSLT 2.0 中的其他一些新特性。



 


 

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