首頁  >  文章  >  後端開發  >  利用XSLT把ADO記錄集轉換成XML

利用XSLT把ADO記錄集轉換成XML

黄舟
黄舟原創
2017-02-27 16:33:381329瀏覽

由於xml(可擴展標記語言:eXtensible Markup Language)真正的平台無關性,它正在逐漸成為資料傳輸的主要媒體。 XML是一種自描述的語言,數據本身就已經包含了元數據,即關於數據本身的信 息。例如:「孟子E章1757281793923net_lover1807581793923」這組數據,從字面很難看出它代表什麼意思,也不清楚它有幾個數據段組成,但是,如果用XML來做如下的描述,我們就可以清楚地看到每個資料段所代表的意義:
 

<PersonData>
  <Person>
   <姓名>孟子E章</姓名>
   <身高>175</身高>
   <体重>72</体重>
   <电话>81793923</电话>
  </Person>  
  <Person>
   <姓名>net_lover</姓名>
   <身高>180</身高>
   <体重>75</体重>
   <电话>81793923</电话>
  </Person>
 </PersonData>

      從上面的一段XML中,我們不但可以清楚地看到每一個資料代表的是什麼意思了,而且還可以知道資料的分割位置。在我們平常的應用中,我們得到的結果可能是 陣列、集合或記錄集的表現形式,我們該如何把它們轉換成自描述的XML格式的資料呢?從資料形式來看,XML是簡單的純字串的文字格式,字串在傳遞時是非常簡單、快速且是容易的,數組在透過引用進行傳遞時有時是很慢的,而且處理起來很麻煩,而集合和記錄集都是對象,在處理時會導致計算機性能的下降, 而這些對像都是與特定的平台相關聯的,這就要求平台有內建的處理機制來處理對象的操作。 XML已經是W3C的標準,是平台無關的,我們的電腦的唯一要求就是能夠處理簡單的XML字串,即XML解析器,它能夠解析XML字串,能夠透過一種介面很容易地把資料分解成一個獨立的資料段,以便我們能夠進行存取。 XML解析器都很小,效能也很好,在每種平台上都可以找到。一旦我們接收到XML資料並把它解析成上面的範例的樣式後,我們就可以透過XSLT (eXstensible Stylesheet Language Transformations)把他們轉換成不同的表現形式。利用XML的資料格式進行資料傳輸,將會使我們編寫應用程式程式碼的工作更簡單輕鬆,而且具有 有良好的可擴展性。
 下面,我們就來看看如何來轉換我們的資料。我們的例子是在Microsoft Windows 2000,IIS5,MSXML3和ADO2.6下編寫的,範例資料採用Microsoft SQL Server7.0自帶的Northwind範例資料庫。之所以採用SQL Server7而不採用支援XML的SQL Server2000,是考慮到通用性的原則,我們的目的是:處理不同類型的資料來源所得到的記錄集,而不僅僅是像SQL Server2000那樣的支援XML輸出的資料來源。使用ADO,是因為它形式多樣,可以處理不同類型的資料來源;使用XML,因為它能夠快速傳輸和解 析。但本例的處理方法也適合在任何具有Micrsoft XML解析器,ADO2.5以上版本的Windows,IIS,SQL Server的環境中。
 為簡單起見,我們只選擇單價小於等於20美圓,庫存大於等於20,產品名稱小於等於6個字元的產品:
 
 

<%
  Dim objRecordset
  Set objRecordset = Server.CreateObject("ADODB.Recordset")
  objRecordset.open _
      "SELECT PRoductName, UnitPrice, UnitsInStock " _
          & "FROM Products " _
          & "WHERE UnitPrice <= 20 " _
          & "AND UnitsInStock >= 20 " _
          & "AND LEN(ProductName) <= 6 " _
          & "ORDER BY ProductName", _
      "Provider=SQLOLEDB;" _
          & "Data Source=SomeSQLServer;" _
          & "Initial Catalog=Northwind;" _
          & "User ID=MyUserName;" _
          & "PassWord=MyPassword;"
  %>

 現在,我們就用3種方式把我們得到的記錄集轉換成XML格式。
 首先,我們可以遍歷整個記錄集,採用XML DOM(Document Object Model),建立XML節點樹:

<%
  Dim objXMLDOM, objRootNode, objNode
  Set objXMLDOM = Server.CreateObject("MSXML2.DOMDocument")
  
  Set objRootNode = objXMLDOM.createElement("xml")
  objXMLDOM.documentElement = objRootNode
  
  Do While NOT objRecordset.EOF
      Set objRowNode = objXMLDOM.createElement("row")  
      Set objNode = objXMLDOM.createElement("ProductName")
      objNode.text = objRecordset.Fields.Item("ProductName").Value
      objRowNode.appendChild(objNode)
  
      Set objNode = objXMLDOM.createElement("UnitPrice")
      objNode.text = objRecordset.Fields.Item("UnitPrice").Value
      objRowNode.appendChild(objNode)
  
      Set objNode = objXMLDOM.createElement("UnitsInStock")
      objNode.text = objRecordset.Fields.Item("UnitsInStock").Value
      objRowNode.appendChild(objNode)
  
      objRootNode.appendChild(objRowNode)
  
      objRecordset.MoveNext
  Loop
  
  Set objNode = Nothing
  Set objRowNode = Nothing
  Set objRootNode = Nothing
  
  Set objRecordset = Nothing
  %>

 現在,我們就得到了一個XML DOM物件。這種方法對於記錄集很大時效能並不理想,因為系統記憶體中要同時保存ADO記錄集物件和XML DOM物件。
 第二個辦法,遍歷記錄集,直接產生XML字串本身:
 

 <%
  Dim strXML
  strXML = "<xml>"
  objRecordset.MoveFirst
  Do While NOT objRecordset.EOF
      strXML = strXML & "<row>"
      strXML = strXML & "<ProductName>" _
          & objRecordset.Fields.Item("ProductName").Value _
          & "</ProductName>"
      strXML = strXML & "<UnitPrice>" _
          & objRecordset.Fields.Item("UnitPrice").Value _
          & "</UnitPrice>"
      strXML = strXML & "<UnitsInStock>" _
          & objRecordset.Fields.Item("UnitsInStock").Value _
          & "</UnitsInStock>"
      strXML = strXML & "</row>"
      objRecordset.MoveNext
  Loop
  strXML = strXML & "</xml>"
  Set objRecordset = Nothing
  %>

  
  但是,以上兩種方法最大的缺陷是無法重複使用程式碼,我們把節點的名字都寫死了,如果我們進行不同欄位的查詢,我們還必須手動更改我們的程式碼,以滿足不同節點的需要。我們下面的方法將變得更加通用。
  第三種方法:可重複使用的方法。
  

  <%
  Dim strXML
  strXML = "<xml>"
  objRecordset.MoveFirst
  Do While NOT objRecordset.EOF
      strXML = strXML & "<row>"
      For Each varItem In objRecordset.Fields
          strXML = strXML _
              & "<" & varItem.name & ">" _
              & varItem.value _
              & "</" & varItem.name & ">"
      Next
      strXML = strXML & "</row>"
      objRecordset.MoveNext
  Loop
  strXML = strXML & "</xml>"
  Set objRecordset = Nothing
  %>

 
  更有效的方法,我們可以直接利用記錄集內建的save方法,它能夠自動地將記錄集的內容轉換成XML格式,我們調用save方法後,我們就可以立即釋放記憶體中的記錄集物件實例。 save方法有兩個參數:一個是XML要保存的地方,一個是指示符,標明資料以何種格式儲存。我們可以把資料保存成XML DOM物件(ADO STREAM物件),也可以直接儲存成asp RESPONSE對象,為通用起見,我們儲存成XML DOM,第二個參數用adPersistXML ADO常數。方法如下:
 

  <%
  Const adPersistXML = 1
  Dim objXMLDOM
  Set objXMLDOM = Server.CreateObject("MSXML2.DOMDocument.3.0")
  objRecordset.save objXMLDOM, adPersistXML
  Set objRecordset = Nothing
  %>

  
 這種方法方便快捷,而且不容易出錯,對不同的查詢,也不用手動更改節點名字。但是,這種方法產生的XML不夠簡潔,看看它產生的結果:
 

<xml    
xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"    
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"    
xmlns:rs="urn:schemas-microsoft-com:rowset"    
xmlns:z="#RowsetSchema">
<s:Schema id="RowsetSchema">
    <s:ElementType        
    name="row"        
    content="eltOnly"        
    rs:CommandTimeout="30">
        <s:AttributeType            
        name="ProductName"           
         rs:number="1"            
         rs:writeunknown="true">
            <s:datatype                
            dt:type="string"                
            dt:maxLength="40"                
            rs:maybenull="false"/>        
            </s:AttributeType>
        <s:AttributeType            
        name="UnitPrice"            
        rs:number="2"            
        rs:nullable="true"            
        rs:writeunknown="true">
            <s:datatype                
            dt:type="number"                
            rs:dbtype="currency"                
            dt:maxLength="8"                
            rs:precision="19"                
            rs:fixedlength="true"/>        
            </s:AttributeType>
        <s:AttributeType            
        name="UnitsInStock"            
        rs:number="3"            
        rs:nullable="true"            
        rs:writeunknown="true">
            <s:datatype                
            dt:type="i2"                
            dt:maxLength="2"                
            rs:precision="5"                
            rs:fixedlength="true"/>        
            </s:AttributeType>
        <s:extends type="rs:rowbase"/>
    </s:ElementType>
</s:Schema>
<rs:data>
    <z:row        ProductName="Chai"        UnitPrice="18"        UnitsInStock="39"/>
    <z:row        ProductName="Konbu"        UnitPrice="6"        UnitsInStock="24"/>
    <z:row        ProductName="Tofu"        UnitPrice="23.25"        UnitsInStock="35"/>
</rs:data>
</xml>

 ADO 自动产生的XML包含了schema信息,它描述这个XML里允许有什么节点和属性以及采用何种数据类型,而且数据节点也增加了名称空间。schema信 息在需要数据验证的地方或进行更复杂的处理或许很有用,但是,大多数情况下,我们使用的是瘦客户机,我们不需要schema信息。我们可以利用XSLT来 分离出我们想要的信息,去掉多余的信息。因此,我们编写下面的“ DataCleaner.xsl”:

 <?xml version="1.0"?>
  <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
      xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
      xmlns:rs="urn:schemas-microsoft-com:rowset"
      xmlns:z="#RowsetSchema">
  
  <xsl:output omit-xml-declaration="yes"/>
  <xsl:template match="/">
      <xsl:element name="xml">
          <xsl:for-each select="/xml/rs:data/z:row">
              <xsl:element name="row">
                  <xsl:for-each select="@*">
                      <xsl:element name="{name()}">
                          <xsl:value-of select="."/>
                      </xsl:element>
                  </xsl:for-each>
              </xsl:element>
          </xsl:for-each>
      </xsl:element>
  </xsl:template>
  
  </xsl:stylesheet>

  
 这个XSLT具有可重用的特性,对于不同的查询结果都适用,下面就是如何使用这个XSLT的例子:
 

  <%
  Dim strCleanXML, objXMLDOM_XSLT
  
  Set objXMLDOM_XSLT = CreateObject("MSXML2.DOMDocument")
  objXMLDOM_XSLT.load(Server.MapPath("DataCleaner.xsl"))
  strCleanXML = objXMLDOM.transformNode(objXMLDOM_XSLT)
  
  Set objXMLDOM = Nothing
  Set objXMLDOM_XSLT = Nothing
  %>

  
 经过上面的处理以后,strClaenXML就是我们所想要的XML字符串了。
  
 

 <xml>
      <row>
          <ProductName>Chai</ProductName>
          <UnitPrice>18</UnitPrice>
          <UnitsInStock>39</UnitsInStock>
      </row>
      <row>
          <ProductName>Konbu</ProductName>
          <UnitPrice>6</UnitPrice>
          <UnitsInStock>24</UnitsInStock>
      </row>
  </xml>

  
 上面这种格式的XML字符串是我们经常见到的节点集的样式,如果您不想把字段处理成节点,而把它处理成属性节点,那么我们只需对DataCleaber.xsl稍加改动即可:

<?xml version="1.0"?>
  <xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
      xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
      xmlns:rs="urn:schemas-microsoft-com:rowset"
      xmlns:z="#RowsetSchema">
  
  <xsl:output omit-xml-declaration="yes"/>
  
  <xsl:template match="/">
      <xsl:element name="xml">
          <xsl:for-each select="/xml/rs:data/z:row">
              <xsl:element name="row">
                  <xsl:for-each select="@*">
                      <xsl:attribute name="{name()}">
                          <xsl:value-of select="."/>
                      </xsl:attribute>
                  </xsl:for-each>
              </xsl:element>
          </xsl:for-each>
      </xsl:element>
  </xsl:template>
  
  </xsl:stylesheet>


 以下是采用了新样式的结果,它比用节点表示字段的长度要短的多了。传输起来速度会更快:
 
 

<xml>
   <row ProductName="Chai" UnitPrice="18" UnitsInStock="39"/>
   <row ProductName="Konbu" UnitPrice="6" UnitsInStock="24"/>
  </xml>

  
  到此为止,我们介绍了从ADO 记录集得到XML格式数据的几种办法,也得到了最简化的字符串。但是有几个问题你仍然需要注意,有些字段值还有XML里不支持的字符,比如:"'6d267e5fab17ea8bc578f9e7e5e1570b&,象P&G宝洁公司的名称,Chef Anton's Gumbo Mix产品名字等,在做转换时要进行编码处理。在Microsoft ADO 2.6的SDK里有使用save方法时要注意的问题:1,save方法只对open Recordset起作用;2,不支持带有adVariant,adIDispatch,adIUnknown类型的字段的记录集的savw;3,当保存 分级的记录集( data shapes)有两个限制:不能保存参数化和含有未解决的更新的记录集。
 为了更进一步提高性能,你可以把转换工作放 到COM/COM+组件中, ASP代码只进行数据的最终表现即可。把业务层、数据层和表现层分开,ASP只需要调用数据组件,数据组件调用数据库的存储过程,把结果转换成XML,最 后只把简单的XML字符环串回到ASP程序里,ASP就可以用XSLT把XML进行转换,把结果送到浏览器。


 以上就是利用XSLT把ADO记录集转换成XML的内容,更多相关内容请关注PHP中文网(www.php.cn)!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn