Gerando XML no SQL Server – Arte do FOR XML PATH

FOR XML

Partimos para o FOR XML PATH, que torna a Arte do FOR XML extremamente flexível, permitindo que o FOR XML PATH seja adequado para suprir qualquer necessidade de geração de XML por meio de T-SQL.

Vamos para o primeiro exemplo desta facilidade, onde criaremos um XML simples a partir de uma consulta, na qual as colunas relacionadas serão os nós filhos:

SELECT TOP (3)
	  FirstName
	, LastName
FROM
	Person.Contact
FOR XML PATH('Contacts'), ROOT('Person')
<Person>
  <Contacts>
    <FirstName>Gustavo</FirstName>
    <LastName>Achong</LastName>
  </Contacts>
  <Contacts>
    <FirstName>Catherine</FirstName>
    <LastName>Abel</LastName>
  </Contacts>
  <Contacts>
    <FirstName>Kim</FirstName>
    <LastName>Abercrombie</LastName>
  </Contacts>
</Person>

E com uma pequena variação (@), temos ao invés de nós filhos, atributos:

SELECT TOP (3)
	  FirstName AS [@FirstName]
	, LastName AS [@LastName]
FROM
	Person.Contact
FOR XML PATH('Contacts'), ROOT('Person')
<Person>
  <Contacts FirstName="Gustavo" LastName="Achong" />
  <Contacts FirstName="Catherine" LastName="Abel" />
  <Contacts FirstName="Kim" LastName="Abercrombie" />
</Person>

Para quem já percebeu com os exemplos anteriores, com o FOR XML PATH temos uma interpretação simplificada do XPATH na geração dos nós e atributos, assim podemos criar facilmente caminhos com atributos, elementos e até comentários de forma totalmente livre:

SELECT TOP (3)
	  LastName AS [Name/@LastName] -- Atributo
	, FirstName AS [Name/text()] -- Texto
	, EmailAddress AS [Contact/Email/text()] -- Texto
	, Phone AS [Contact/Phone] -- Texto, sem 'text()'
	, ModifiedDate AS [comment()] -- Comentário
FROM
	Person.Contact
FOR XML PATH('Contacts'), ROOT('Person')
<Person>
  <Contacts>
    <Name LastName="Achong">Gustavo</Name>
    <Contact>
      <Email>gustavo0@adventure-works.com</Email>
      <Phone>398-555-0132</Phone>
    </Contact>
    <!--2005-05-16T16:33:33.060-->
  </Contacts>
  <Contacts>
    <Name LastName="Abel">Catherine</Name>
    <Contact>
      <Email>catherine0@adventure-works.com</Email>
      <Phone>747-555-0171</Phone>
    </Contact>
    <!--2005-05-16T16:33:33.077-->
  </Contacts>
  <Contacts>
    <Name LastName="Abercrombie">Kim</Name>
    <Contact>
      <Email>kim2@adventure-works.com</Email>
      <Phone>334-555-0137</Phone>
    </Contact>
    <!--2005-05-16T16:33:33.077-->
  </Contacts>
</Person>

Dai iniciam os desafios para gerar uma HTML TABLE com várias colunas no FOR XML PATH, sendo as próximas consultas não obtendo o resultado esperado:

Erro 1: Representação de duas colunas no mesmo path gera texto concatenado:

SELECT TOP (3)
	  FirstName AS [TD]
	  ,LastName AS [TD]
FROM
	Person.Contact
FOR XML PATH('TR'), ROOT('TABLE')
<TABLE>
  <TR>
    <TD>GustavoAchong</TD>
  </TR>
  <TR>
    <TD>CatherineAbel</TD>
  </TR>
  <TR>
    <TD>KimAbercrombie</TD>
  </TR>
</TABLE>

Erro 2: Texto com nós XML é transformado (encode):

SELECT TOP (3)
	  '<TD>' + FirstName + '</TD>',
	  '<TD>' + LastName + '</TD>'
FROM
	Person.Contact
FOR XML PATH('TR'), ROOT('TABLE')
<TABLE>
  <TR>&lt;TD&gt;Gustavo&lt;/TD&gt;&lt;TD&gt;Achong&lt;/TD&gt;</TR>
  <TR>&lt;TD&gt;Catherine&lt;/TD&gt;&lt;TD&gt;Abel&lt;/TD&gt;</TR>
  <TR>&lt;TD&gt;Kim&lt;/TD&gt;&lt;TD&gt;Abercrombie&lt;/TD&gt;</TR>
</TABLE>

Solução: Para solução deste problema, temos as seguintes alternativas:

-- Gerando um path vazio, exigindo do SQL Server a criação de dois nós separados
SELECT TOP (3)
	  FirstName AS [TD]
	, NULL AS [text()]
	, LastName AS [TD]
FROM
	Person.Contact
FOR XML PATH('TR'), ROOT('TABLE')

-- Gerando o XML por conversão de dados
SELECT TOP (3)
	  CAST('<TD>' + FirstName + '</TD><TD>' + LastName + '</TD>' AS XML)
FROM
	Person.Contact
FOR XML PATH('TR'), ROOT('TABLE')

-- Gerando o XML por subconsulta
SELECT TOP (3)
	  (SELECT FirstName AS [text()] FOR XML PATH('TD'), TYPE)
	, (SELECT LastName AS [text()] FOR XML PATH('TD'), TYPE)
FROM
	Person.Contact
FOR XML PATH('TR'), ROOT('TABLE')
<TABLE>
  <TR>
    <TD>Gustavo</TD>
    <TD>Achong</TD>
  </TR>
  <TR>
    <TD>Catherine</TD>
    <TD>Abel</TD>
  </TR>
  <TR>
    <TD>Kim</TD>
    <TD>Abercrombie</TD>
  </TR>
</TABLE>
Please follow and like us:

Deixe um comentário

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.