XML(Extensible Markup Language: eXtensible Markup Language)의 진정한 플랫폼 독립성으로 인해 점차 데이터 전송의 주요 매체로 자리잡고 있습니다. XML은 자기 설명적 언어이며 데이터 자체에는 이미 메타데이터, 즉 데이터 자체에 대한 정보가 포함되어 있습니다. 예: "맹자 Chapter 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 데이터를 수신하여 위 예제의 스타일로 구문 분석하면 XSLT(eXstensible Stylesheet Language Transformations)를 통해 이를 다른 표현으로 변환할 수 있습니다. 데이터 전송에 XML 데이터 형식을 사용하면 애플리케이션 코드 작성 작업이 더 간단하고 쉬워지며 확장성이 좋습니다.
다음으로 데이터를 변환하는 방법을 살펴보겠습니다. 우리의 예제는 Microsoft Windows 2000, IIS5, MSXML3 및 ADO2.6에서 작성되었습니다. 샘플 데이터는 Microsoft SQL Server7.0과 함께 제공되는 Northwind 샘플 데이터베이스를 사용합니다. XML을 지원하는 SQL Server2000 대신 SQL Server7을 사용하는 이유는 보편성의 원칙 때문입니다. 우리의 목적은 SQL Server2000과 같은 XML 출력을 지원하는 것이 아니라 다양한 유형의 데이터 소스에서 얻은 레코드 세트를 처리하는 것입니다. ADO는 다양한 형식을 가지며 다양한 유형의 데이터 소스를 처리할 수 있기 때문에 사용됩니다. XML은 빠르게 전송하고 구문 분석할 수 있기 때문에 사용됩니다. 하지만 이 예제의 처리 방법은 Microsoft 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 %>
더 효과적인 방법은 레코드 세트의 내용을 자동으로 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里不支持的字符,比如:"'< >&,象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)!