Meng Xianhui
XML(Extensible Markup Language: eXtensible Markup Language)의 진정한 플랫폼 독립성으로 인해 XML은 점차 데이터 전송의 주요 매체로 자리잡고 있습니다. XML은 자기 설명적 언어이며 데이터 자체에는 이미 메타데이터, 즉 데이터 자체에 대한 정보가 포함되어 있습니다. 예: "맹자 Chapter E 1757281793923net_lover1807581793923" 이 데이터 세트는 문자 그대로 무엇을 의미하는지 알기 어렵고, 얼마나 많은 데이터 세그먼트로 구성되어 있는지 명확하지 않습니다. 그러나 이를 다음과 같이 설명하기 위해 XML을 사용하면 다음과 같습니다. 각 데이터 세그먼트의 의미를 명확하게 볼 수 있습니다.
<개인데이터>
<사람>
<Name>맹자 E장</Name>
<높이>175</높이>
<무게>72</무게>
<Tel>81793923</Tel>
</사람>
<사람>
<name>net_lover</name>
<높이>180</높이>
<무게>75</무게>
<Tel>81793923</Tel>
</사람>
</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자 이하인 제품만 선택합니다.
<%
희미한 objRecordset
objRecordset = Server.CreateObject("ADODB.Recordset") 설정
objRecordset.open _
"제품 이름, 단가, 재고 보유 단위 선택" _
& "제품에서" _
& "WHERE 단가 <= 20 " _
& "AND 재고 보유 단위 >= 20 " _
& "AND LEN(제품명) <= 6 " _
& "제품명별 주문", _
"공급자=SQLOLEDB;"
& "데이터 소스=SomeSQLServer;"
& "초기 카탈로그=Northwind;"
& "사용자 ID=내 사용자 이름;"
& "비밀번호=내 비밀번호;"
%>
이제 3가지 방법을 사용하여 얻은 레코드 세트를 XML 형식으로 변환합니다.
첫째, 전체 레코드 세트를 탐색하고 XML DOM(Document Object Model)을 사용하여 XML 노드 트리를 구축할 수 있습니다.
<%
희미한 objXMLDOM, objRootNode, objNode
objXMLDOM = Server.CreateObject("MSXML2.DOMDocument") 설정
objRootNode = objXMLDOM.createElement("xml") 설정
objXMLDOM.documentElement = objRootNode
objRecordset.EOF가 아닌 동안 수행
objRowNode = objXMLDOM.createElement("행") 설정
objNode = objXMLDOM.createElement("제품 이름") 설정
objNode.text = objRecordset.Fields.Item("제품 이름").Value
objRowNode.appendChild(objNode)
objNode = objXMLDOM.createElement("UnitPrice") 설정
objNode.text = objRecordset.Fields.Item("UnitPrice").Value
objRowNode.appendChild(objNode)
objNode = objXMLDOM.createElement("UnitsInStock") 설정
objNode.text = objRecordset.Fields.Item("UnitsInStock").Value
objRowNode.appendChild(objNode)
objRootNode.appendChild(objRowNode)
objRecordset.MoveNext
고리
objNode = 없음으로 설정
objRowNode = 없음으로 설정
objRootNode = 없음으로 설정
objRecordset = 아무것도 설정하지 않음
%>
이제 XML DOM 객체가 생겼습니다. ADO 레코드 집합 개체와 XML DOM 개체가 동시에 시스템 메모리에 저장되어야 하기 때문에 이 방법의 성능은 레코드 집합이 클 때 이상적이지 않습니다.
두 번째 방법은 레코드 세트를 탐색하여 XML 문자열 자체를 직접 생성하는 것입니다.
<%
희미한 strXML
strXML = "<xml>"
objRecordset.MoveFirst
objRecordset.EOF가 아닌 동안 수행
strXML = strXML & "<행>"
strXML = strXML & "<제품 이름>" _
& objRecordset.Fields.Item("제품 이름").Value _
& "</제품 이름>"
strXML = strXML & "<단가>" _
& objRecordset.Fields.Item("UnitPrice").Value _
& "</단가>"
strXML = strXML & "<UnitsInStock>" _
& objRecordset.Fields.Item("UnitsInStock").Value _
& "</UnitsInStock>"
strXML = strXML & "</row>"
objRecordset.MoveNext
고리
strXML = strXML & "</xml>"
objRecordset = 아무것도 설정하지 않음
%>
그러나 위 두 가지 방법의 가장 큰 결점은 코드를 재사용할 수 없다는 점입니다. 노드의 이름을 적어 두었습니다. 다른 필드를 쿼리하는 경우에도 다른 노드의 요구 사항에 맞게 코드를 수동으로 변경해야 합니다. 아래의 접근 방식은 더욱 일반화될 것입니다.
세 번째 방법: 재사용 가능한 방법.
<%
희미한 strXML
strXML = "<xml>"
objRecordset.MoveFirst
objRecordset.EOF가 아닌 동안 수행
strXML = strXML & "<행>"
objRecordset.Fields의 각 varItem에 대해
strXML = strXML _
& "<" & varItem.name & ">" _
&varItem.value_
& "</" & varItem.name & ">"
다음
strXML = strXML & "</row>"
objRecordset.MoveNext
고리
strXML = strXML & "</xml>"
objRecordset = 아무것도 설정하지 않음
%>
보다 효과적인 방법은 레코드세트의 내용을 자동으로 XML 형식으로 변환할 수 있는 내장된 레코드세트 저장 메소드를 직접 사용하는 것입니다. 저장 메소드를 호출한 후 메모리에서 레코드세트 객체 인스턴스를 즉시 해제할 수 있습니다. . save 메소드에는 두 개의 매개변수가 있습니다. 하나는 XML이 저장될 위치이고 다른 하나는 데이터가 저장되는 형식을 나타내는 표시기입니다. 데이터를 XML DOM 객체(ADO STREAM 객체)로 저장할 수도 있고, 일반화를 위해 ASP RESPONSE 객체로 직접 저장할 수도 있으며, 두 번째 매개변수에는 adPersistXML ADO 상수를 사용합니다. . 방법은 다음과 같습니다.
<%
상수 adPersistXML = 1
희미한 objXMLDOM
objXMLDOM = Server.CreateObject("MSXML2.DOMDocument.3.0") 설정
objRecordset.save objXMLDOM, adPersistXML
objRecordset = 아무것도 설정하지 않음
%>
이 방법은 편리하고 빠르며 오류가 없습니다. 다른 쿼리에 대해 노드 이름을 수동으로 변경할 필요가 없습니다. 그러나 이 방법으로 생성된 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
이름="행"
content="eltOnly"
rs:CommandTimeout="30">
<s:AttributeType
name="제품명"
RS:번호="1"
rs:writeunknown="true">
<s:데이터 유형
dt:유형="문자열"
dt:maxLength="40"
rs:maybenull="false"/>
</s:속성유형>
<s:속성유형
이름="단가"
RS:번호="2"
rs:nullable="true"
rs:writeunknown="true">
<s:데이터 유형
dt:type="번호"
rs:dbtype="통화"
dt:maxLength="8"
RS:정밀도="19"
rs:고정길이="true"/>
</s:속성유형>
<s:속성유형
name="재고 단위"
RS:번호="3"
rs:nullable="true"
rs:writeunknown="true">
<s:데이터 유형
dt:유형="i2"
dt:maxLength="2"
RS:정밀도="5"
rs:고정길이="true"/>
</s:AttributeType>
<s:extends type="rs:rowbase"/>
</s:ElementType>
</s:Schema>
<rs:data>
<z:row
제품명="차이"
단가="18"
UnitsInStock="39"/>
<z:row
ProductName="콘부"
단가="6"
UnitsInStock="24"/>
<z:row
제품명="두부"
단가="23.25"
UnitsInStock="35"/>
</rs:data>
</xml>
ADO에서 자동으로 생성된 XML에는 이 XML에서 허용되는 노드와 속성, 사용되는 데이터 유형 및 데이터 노드를 설명하는 스키마 정보가 포함되어 있습니다. 네임스페이스도 증가했습니다. 스키마 정보는 데이터 유효성 검사가 필요하거나 보다 복잡한 처리에 유용할 수 있지만 대부분의 경우 씬 클라이언트를 사용하므로 스키마 정보가 필요하지 않습니다. XSLT를 사용하여 원하는 정보를 분리하고 중복 정보를 제거할 수 있습니다. 따라서 다음 "DataCleaner.xsl"을 작성합니다.
<?xml 버전="1.0"?>
<xsl:스타일시트 버전="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 생략-xml-declaration="yes"/>
<xsl:템플릿 일치="/">
<xsl:요소 이름="xml">
<xsl:for-each select="/xml/rs:data/z:row">
<xsl:요소 이름="행">
<xsl:for-each select="@*">
<xsl:요소 이름="{name()}">
<xsl:value-of select="."/>
</xsl:요소>
</xsl:for-each>
</xsl:요소>
</xsl:for-each>
</xsl:요소>
</xsl:템플릿>
</xsl:스타일시트>
이 XSLT에는 재사용 가능한 기능이 있으며 다양한 쿼리 결과에 적용할 수 있습니다. 다음은 이 XSLT를 사용하는 방법에 대한 예입니다.
<%
희미한 strCleanXML, objXMLDOM_XSLT
objXMLDOM_XSLT = CreateObject("MSXML2.DOMDocument") 설정
objXMLDOM_XSLT.load(Server.MapPath("DataCleaner.xsl"))
strCleanXML = objXMLDOM.transformNode(objXMLDOM_XSLT)
objXMLDOM = 없음으로 설정
objXMLDOM_XSLT = 없음으로 설정
%>
위의 처리 후 strClaenXML은 우리가 원하는 XML 문자열입니다.
<xml>
<행>
<ProductName>차이</ProductName>
<단가>18</단가>
<UnitsInStock>39</UnitsInStock>
</row>
<행>
<ProductName>콘부</ProductName>
<단가>6</단가>
<UnitsInStock>24</UnitsInStock>
</row>
</xml>
위 형식의 XML 문자열은 우리가 자주 보는 노드 세트의 스타일입니다. 필드를 노드로 처리하지 않고 속성 노드로 처리하려면 DataCleaber를 약간만 변경하면 됩니다. xsl:
<?xml 버전="1.0"?>
<xsl:스타일시트 버전="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 생략-xml-declaration="yes"/>
<xsl:템플릿 일치="/">
<xsl:요소 이름="xml">
<xsl:for-each select="/xml/rs:data/z:row">
<xsl:요소 이름="행">
<xsl:for-each select="@*">
<xsl:속성 이름="{name()}">
<xsl:value-of select="."/>
</xsl:속성>
</xsl:for-each>
</xsl:요소>
</xsl:for-each>
</xsl:요소>
</xsl:템플릿>
</xsl:스타일시트>
다음은 필드의 길이를 표현하기 위해 노드를 사용하는 것보다 훨씬 짧은 새로운 스타일을 사용한 결과입니다. 전송 속도가 더 빨라집니다:
<xml>
<row ProductName="Chai" UnitPrice="18" UnitsInStock="39"/>
<row ProductName="콘부" UnitPrice="6" UnitsInStock="24"/>
</xml>
지금까지 우리는 ADO 레코드 세트에서 XML 형식 데이터를 얻는 여러 가지 방법을 소개했으며 가장 단순화된 문자열도 얻었습니다. 그러나 여전히 주의해야 할 몇 가지 문제가 있습니다. 일부 필드 값에는 다음과 같이 XML에서 지원되지 않는 문자가 있습니다. "'< >&(예: P&G Procter & Gamble 이름) Chef Anton의 Gumbo Mix 제품 등 변환 시 이 작업을 수행해야 합니다. Microsoft ADO 2.6 SDK에서 저장 방법을 사용할 때 주의해야 할 문제가 있습니다. 1. 저장 방법은 열린 레코드 집합에서만 작동합니다. adVariant, adIDispatch 및 adIUnknown 유형의 필드는 지원되지 않습니다. 3. 계층적 레코드 집합(데이터 셰이프)을 저장할 때 두 가지 제한 사항이 있습니다. 즉, 해결되지 않은 업데이트가 포함된 레코드 집합은 저장할 수 없습니다.
성능을 더욱 향상시키기 위해 변환 작업을 COM/COM+ 구성 요소에 넣을 수 있으며 ASP 코드는 데이터의 최종 프레젠테이션만 수행합니다. 비즈니스 계층, 데이터 계층 및 프레젠테이션 계층을 분리하면 ASP는 데이터 구성 요소만 호출하면 됩니다. 데이터 구성 요소는 데이터베이스의 저장 프로시저를 호출하고 결과를 XML로 변환하며 마지막으로 간단한 XML 문자열만 ASP 프로그램에 반환합니다. , ASP는 XSLT를 사용하여 XML을 변환하고 결과를 브라우저로 보낼 수 있습니다.