The EXPLICIT keyword gives you the most flexibility, but at the same time, it is the most complex. The SELECT statement itself is used to form the hierarchy of XML elements and attributes. In the most basic form, the first column (always an integer value labeled as Tag) specified in the statement indicates the current XML element. The second column (labeled as Parent) indicates which element is the parent of the current element (and can be set to 0 or NULL if the current element is the top one). Both values are referenced in the subsequent columns, (actual columns from the target table), to determine their relative placement. These columns are converted to XML elements or attributes using the following notation:
Element!Tag!Attribute!Directive
Where Element designates the arbitrarily chosen name of the XML element and Tag is the number of the element (as explained above). The meaning of Attribute depends on the value of Directive. If Directive is omitted, then Attribute is used as the name of the XML attribute: if Directive is set to the value element, then Attribute is used as the name of the XML element (Directive can have a number of other values - for more information refer to the SQL Books Online). This should become clearer with the help of a few examples. The following SELECT statement:
SELECT 1 AS Tag,
NULL AS Parent,
ShipperID AS [ShippersElement!1!ShipperIDAttribute],
CompanyName AS [ShippersElement!1!CompanyNameAttribute],
Phone AS [ShippersElement!1!PhoneAttribute]
FROM Shippers
FOR XML EXPLICIT
Produces the output in the form:
<ShippersElement ShipperIDAttribute="1" CompanyNameAttribute="Speedy Express"
PhoneAttribute="(503) 555-9831"/>
<ShippersElement ShipperIDAttribute="2" CompanyNameAttribute="United Package"
PhoneAttribute="(503) 555-3199"/>
<ShippersElement ShipperIDAttribute="3" CompanyNameAttribute="Federal Shipping"
PhoneAttribute="(503) 555-9931"/>
We could easily change the attributes in the output into elements by including the element directive:
SELECT 1 AS Tag,
NULL AS Parent,
ShipperID AS [ShippersElement!1!ShipperIDAttribute!element],
CompanyName AS [ShippersElement!1!CompanyNameAttribute!element],
Phone AS [ShippersElement!1!PhoneAttribute!element]
FROM Shippers
FOR XML EXPLICIT
Which would give us:
<ShippersElement>
<ShipperIDAttribute>1</ShipperIDAttribute>
<CompanyNameAttribute>Speedy Express</CompanyNameAttribute>
<PhoneAttribute>(503)555-9831</PhoneAttribute>
</ShippersElement>
<ShippersElement>
<ShipperIDAttribute>2</ShipperIDAttribute>
<CompanyNameAttribute>United Package</CompanyNameAttribute>
<PhoneAttribute>(503) 555-3199</PhoneAttribute>
</ShippersElement>
<ShippersElement>
<ShipperIDAttribute>3</ShipperIDAttribute>
<CompanyNameAttribute>Federal Shipping</CompanyNameAttribute>
<PhoneAttribute>(503) 555-9931</PhoneAttribute>
</ShippersElement>
You can get more creative by using multiple SELECT statements, combined together with the UNION ALL clause (note that this also requires an appropriately formed ORDER BY clause). For example:
SELECT 1 AS Tag,
NULL AS Parent,
ShipperID AS [Shippers!1!ShipperID],
NULL AS [Shippers!2!CompanyName]
FROM Shippers
UNION ALL
SELECT 2,
1,
ShipperID,
CompanyName
FROM Shippers
ORDER BY [Shippers!1!ShipperID],[Shippers!2!CompanyName]
FOR XML EXPLICIT
Which produces the following results:
<Shippers ShipperID="1">
<Shippers CompanyName="Speedy Express"/>
</Shippers>
<Shippers ShipperID="2">
<Shippers CompanyName="United Package"/>
</Shippers>
<Shippers ShipperID="3">
<Shippers CompanyName="Federal Shipping"/>
</Shippers>