Gerando XML no SQL Server – Arte do FOR XML RAW
Seguindo com a Arte do FOR XML, nos deparamos com o FOR XML RAW, que não se diferencia muito do FOR XML AUTO, mas aproveitamos este artigo para demonstrar outros aspectos interessantes tanto do FOR XML RAW quando do FOR XML AUTO (campos nulos, tipos binários e schemas).
Como primeiro passo, temos uma consulta RAW básica:
SELECT TOP (5) FirstName , LastName FROM Person.Contact FOR XML RAW
<row FirstName="Gustavo" LastName="Achong" /> <row FirstName="Catherine" LastName="Abel" /> <row FirstName="Kim" LastName="Abercrombie" /> <row FirstName="Humberto" LastName="Acevedo" /> <row FirstName="Pilar" LastName="Ackerman" />
Seguida de outra um pouco mais customizada:
SELECT TOP (5) [Name] = FirstName + ', ' + LastName FROM Person.Contact FOR XML RAW('Contact') , ELEMENTS , ROOT('Person')
<Person> <Contact> <Name>Gustavo, Achong</Name> </Contact> <Contact> <Name>Catherine, Abel</Name> </Contact> <Contact> <Name>Kim, Abercrombie</Name> </Contact> <Contact> <Name>Humberto, Acevedo</Name> </Contact> <Contact> <Name>Pilar, Ackerman</Name> </Contact> </Person>
Uma questão importante de se verificar é o comportamento da geração do XML (AUTO e RAW) quando tratamos de campos NULL, assim temos a alternativa de não gerar os nós nulos (comportamento padrão):
SELECT TOP (5) [Name] = FirstName + ', ' + LastName , MiddleName FROM Person.Contact FOR XML RAW('Contact') , ELEMENTS ABSENT , ROOT('Person')
<Person> <Contact> <Name>Gustavo, Achong</Name> </Contact> <Contact> <Name>Catherine, Abel</Name> <MiddleName>R.</MiddleName> </Contact> <Contact> <Name>Kim, Abercrombie</Name> </Contact> <Contact> <Name>Humberto, Acevedo</Name> </Contact> <Contact> <Name>Pilar, Ackerman</Name> </Contact> </Person>
Ou utilizar XSINIL para que exista uma representação destes nós nulos:
SELECT TOP (5) [Name] = FirstName + ', ' + LastName , MiddleName FROM Person.Contact FOR XML RAW('Contact') , ELEMENTS XSINIL , ROOT('Person')
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <Contact> <Name>Gustavo, Achong</Name> <MiddleName xsi:nil="true" /> </Contact> <Contact> <Name>Catherine, Abel</Name> <MiddleName>R.</MiddleName> </Contact> <Contact> <Name>Kim, Abercrombie</Name> <MiddleName xsi:nil="true" /> </Contact> <Contact> <Name>Humberto, Acevedo</Name> <MiddleName xsi:nil="true" /> </Contact> <Contact> <Name>Pilar, Ackerman</Name> <MiddleName xsi:nil="true" /> </Contact> </Person>
Campos binários também podem ser problemáticos, exemplo o seguinte erro:
SELECT TOP (1) ProductPhotoID , ThumbNailPhoto FROM Production.ProductPhoto FOR XML RAW
Msg 6829, Level 16, State 1, Line 1
FOR XML EXPLICIT and RAW modes currently do not support addressing binary data as URLs in column ‘ThumbNailPhoto’. Remove the column, or use the BINARY BASE64 mode, or create the URL directly using the ‘dbobject/TABLE[@PK1=”V1″]/@COLUMN’ syntax.
Assim, utilizamos das declarações BINARY BASE64 para tratar este problema:
SELECT TOP (1) ProductPhotoID , ThumbNailPhoto FROM Production.ProductPhoto FOR XML RAW , BINARY BASE64
<row ProductPhotoID="1" ThumbNailPhoto="R0lGODlhUAA..." />
Por fim, temos a necessidade de gerar Schemas ou alguma forma de representação dos tipos de dados que estão presentes no XML, onde podemos utilizar do XMLDATA para uma representação simples dos dados:
SELECT TOP (1) [Name] = FirstName + ', ' + LastName , [Email] = EmailAddress FROM Person.Contact FOR XML RAW , XMLDATA
<Schema name="Schema2" xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes"> <ElementType name="row" content="empty" model="closed"> <AttributeType name="Name" dt:type="string" /> <AttributeType name="Email" dt:type="string" /> <attribute type="Name" /> <attribute type="Email" /> </ElementType> </Schema> <row xmlns="x-schema:#Schema2" Name="Gustavo, Achong" Email="gustavo0@adventure-works.com" />
Ou XMLSCHEMA, para a declaração mais apropriada com Xml Schema definition language (XSD):
SELECT TOP (1) [Name] = FirstName + ', ' + LastName , [Email] = EmailAddress FROM Person.Contact FOR XML RAW('Contact') , ROOT('Person') , XMLSCHEMA('PersonContact')
<Person> <xsd:schema targetNamespace="PersonContact" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes" elementFormDefault="qualified"> <xsd:import namespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes" schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd" /> <xsd:element name="Contact"> <xsd:complexType> <xsd:attribute name="Name" use="required"> <xsd:simpleType> <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreNonSpace IgnoreKanaType IgnoreWidth" sqltypes:sqlCollationVersion="2"> <xsd:maxLength value="102" /> </xsd:restriction> </xsd:simpleType> </xsd:attribute> <xsd:attribute name="Email"> <xsd:simpleType> <xsd:restriction base="sqltypes:nvarchar" sqltypes:localeId="1033" sqltypes:sqlCompareOptions="IgnoreCase IgnoreNonSpace IgnoreKanaType IgnoreWidth" sqltypes:sqlCollationVersion="2"> <xsd:maxLength value="50" /> </xsd:restriction> </xsd:simpleType> </xsd:attribute> </xsd:complexType> </xsd:element> </xsd:schema> <Contact xmlns="PersonContact" Name="Gustavo, Achong" Email="gustavo0@adventure-works.com" /> </Person>