Aufgrund der echten Plattformunabhängigkeit von XML (Extensible Markup Language: eXtensible Markup Language) wird es nach und nach zum Hauptmedium für die Datenübertragung. XML ist eine selbstbeschreibende Sprache und die Daten selbst enthalten bereits Metadaten, also Informationen über die Daten selbst. Zum Beispiel: „Mencius Kapitel E 1757281793923net_lover1807581793923“ Dieser Datensatz ist schwer zu erkennen, was er wörtlich bedeutet, und es ist nicht klar, aus wie vielen Datensegmenten er besteht. Wenn wir jedoch XML verwenden, um ihn wie folgt zu beschreiben Wir können die Bedeutung jedes Datensegments klar erkennen:
<PersonData> <Person> <姓名>孟子E章</姓名> <身高>175</身高> <体重>72</体重> <电话>81793923</电话> </Person> <Person> <姓名>net_lover</姓名> <身高>180</身高> <体重>75</体重> <电话>81793923</电话> </Person> </PersonData>
Aus dem obigen XML-Teil können wir nicht nur klar erkennen, was jedes Datensegment bedeutet, sondern auch wissen, wo sich die Daten befinden ist gespalten. In unseren üblichen Anwendungen können die Ergebnisse in Form von Arrays, Sammlungen oder Recordsets vorliegen. Wie konvertieren wir sie in selbstbeschreibende Daten im XML-Format? Aus Sicht der Datenform ist XML ein einfaches Textformat für reine Zeichenfolgen. Die Übertragung von Arrays per Referenz ist manchmal sehr mühsam und die Verarbeitung und Aufzeichnung ist sehr aufwändig Sätze sind beide Objekte, was zu einer Verringerung der Computerleistung während der Verarbeitung führt, und diese Objekte sind mit einer bestimmten Plattform verknüpft, was erfordert, dass die Plattform über einen integrierten Verarbeitungsmechanismus zur Verarbeitung von Objektoperationen verfügt. XML ist bereits ein W3C-Standard und plattformunabhängig. Die einzige Voraussetzung für unsere Computer ist die Fähigkeit, einfache XML-Strings zu verarbeiten, d unabhängige Datensegmente, damit wir darauf zugreifen können. XML-Parser sind klein, leistungsstark und auf jeder Plattform zu finden. Sobald wir die XML-Daten erhalten und sie im Stil des obigen Beispiels analysieren, können wir sie über XSLT (eXstensible Stylesheet Language Transformations) in verschiedene Darstellungen konvertieren. Durch die Verwendung des XML-Datenformats für die Datenübertragung wird das Schreiben von Anwendungscode einfacher und einfacher und die Skalierbarkeit ist gut.
Als nächstes schauen wir uns an, wie wir unsere Daten konvertieren. Unser Beispiel wurde unter Microsoft Windows 2000, IIS5, MSXML3 und ADO2.6 geschrieben und die Beispieldaten verwenden die Northwind-Beispieldatenbank, die mit Microsoft SQL Server 7.0 geliefert wird. Der Grund, warum SQL Server7 anstelle von SQL Server2000 verwendet wird, liegt im Prinzip der Universalität. Unser Zweck besteht darin, die aus verschiedenen Arten von Datenquellen erhaltenen Datensätze zu verarbeiten und nicht nur die XML-Ausgabe wie SQL Server2000 zu unterstützen. ADO wird verwendet, weil es verschiedene Formen hat und verschiedene Arten von Datenquellen verarbeiten kann; XML wird verwendet, weil es schnell übertragen und analysiert werden kann. Die Verarbeitungsmethode in diesem Beispiel eignet sich jedoch auch für jede Umgebung mit Microsoft XML-Parser, ADO2.5 oder einer höheren Windows-Version, IIS und SQL Server.
Der Einfachheit halber wählen wir nur Produkte aus, deren Stückpreis kleiner oder gleich 20 US-Dollar ist, deren Lagerbestand größer oder gleich 20 ist und deren Produktnamen kleiner oder gleich 6 Zeichen sind:
<% 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;" %>
Jetzt verwenden wir drei Methoden, um den erhaltenen Datensatz in das XML-Format zu konvertieren.
Zuerst können wir den gesamten Datensatz durchlaufen, XML DOM (Document Object Model) verwenden und einen XML-Knotenbaum erstellen:
<% 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 %>
Jetzt haben wir ein XML-DOM-Objekt. Die Leistung dieser Methode ist nicht optimal, wenn das Recordset groß ist, da das ADO-Recordset-Objekt und das XML-DOM-Objekt gleichzeitig im Systemspeicher gespeichert werden müssen.
Die zweite Methode besteht darin, den Datensatz zu durchlaufen und direkt die XML-Zeichenfolge selbst zu generieren:
<% 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 %>
Der größte Fehler der beiden oben genannten Methoden besteht jedoch darin, dass sie nicht wiederverwendet werden können Der Code Wir notieren die Namen der Knoten. Wenn wir Abfragen für verschiedene Felder durchführen, müssen wir unseren Code auch manuell ändern, um den Anforderungen verschiedener Knoten gerecht zu werden. Im Folgenden wird unser Ansatz allgemeiner.
Die dritte Methode: wiederverwendbare Methode.
<% 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 %>
Eine effektivere Methode besteht darin, dass wir direkt die integrierte Speichermethode des Datensatzes verwenden können, mit der der Inhalt des Datensatzes automatisch in konvertiert werden kann XML-Format Nachdem wir die Save-Methode aufgerufen haben, können wir die Recordset-Objektinstanz sofort im Speicher freigeben. Die Speichermethode verfügt über zwei Parameter: Der eine ist der Ort, an dem das XML gespeichert werden soll, und der andere ist ein Indikator, der das Format angibt, in dem die Daten gespeichert werden. Wir können die Daten als XML-DOM-Objekt (ADO-STREAM-Objekt) oder direkt als ASP-RESPONSE-Objekt speichern. Der Allgemeinheit halber speichern wir sie als XML-DOM und verwenden die adPersistXML-ADO-Konstante für den zweiten Parameter . Die Methode lautet wie folgt:
<% Const adPersistXML = 1 Dim objXMLDOM Set objXMLDOM = Server.CreateObject("MSXML2.DOMDocument.3.0") objRecordset.save objXMLDOM, adPersistXML Set objRecordset = Nothing %>
Diese Methode ist bequem und schnell und nicht fehleranfällig. Es ist nicht erforderlich, den Knotennamen für verschiedene Abfragen manuell zu ändern . Das mit dieser Methode erzeugte XML ist jedoch nicht präzise genug. Schauen Sie sich das Ergebnis an:
<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中文网(m.sbmmt.com)!