Beruflich Dokumente
Kultur Dokumente
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
UsingtheFORXMLClausetoReturnQueryResultsasXML
27May2009
byRobertSheldon
TheFORXMLclauseinSQLServercausesalotofdifficulty,mainlybecauseitisratherpoorlyexplainedinBooksonLine.WechallengedBobSheldontomakeitseemsimple.Hereishissublimeresponse.
QLServerletsyouretrievedataasXMLbysupportingtheFORXMLclause,whichcanbeincludedaspartofyourquery.YoucanusetheFORXMLclauseinthemain(outer)queryaswellasinsubqueries.Theclausesupportsnumerousoptionsthatletyou
definetheformatoftheXMLdata.
WhenyouincludetheFORXMLclauseinyourquery,youmustspecifyoneofthefoursupportedmodesRAW,AUTO,EXPLICIT,orPATH.Theoptionsavailabletoeachmodevaryaccordingtothatmodehowever,manyoftheoptionsaresharedamongthemodes.
Inthisarticle,IexplainhowtouseeachofthesemodestoretrievedataasXMLandprovideexamplesthatdemonstratehowtheyusethevariousoptions.
TheRAWMode
TheRAWmodegeneratesasingleXMLelementforeachrowintheresultsetreturnedbythequery.
TousetheFORXMLclauseinRAWmode,yousimplyappendtheclauseandRAWkeywordtoyourSELECTstatement,asshowninthefollowingexample:
SELECTe.EmployeeID,c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLRAW
NoticethattheSELECTstatementitselfisaverybasicquery.(ThestatementpullsdatafromtheAdventureWorkssampledatabase.)WithouttheFORXMLclause,thestatementwouldreturnthefollowingresults:
EmployeeIDFirstNameMiddleNameLastName
4RobNULLWalters
168RobTCaron
WiththeadditionoftheFORXMLclause,thestatementreturnsthedataasthefollowingXML:
<rowEmployeeID="4"FirstName="Rob"LastName="Walters"/>
<rowEmployeeID="168"FirstName="Rob"MiddleName="T"LastName="Caron"/>
Asyoucansee,each<row>elementmapstoarowthatisreturnedbytheSELECTstatement,andeachcolumn,bydefault,istreatedasanattributeofthatelement.
Note:YoucanincludeaFORXMLclauseonlyinSELECTstatements,ifthosestatementsdefinetheouter,ortoplevel,query.However,youcanalsoincludetheclauseinINSERT,UPDATE,andDELETEstatementsthatarepartofasubquery.
Intheprecedingexample,eachelementintheXMLisnamed<row>bydefault.However,youcanoverridethedefaultbehaviorbyprovidinganamefortheelement,asthefollowingexampleshows:
SELECTe.EmployeeID,c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLRAW('Employee')
Nowtheelementassociatedwitheachrowreturnedbythequerywillbenamed<Employee>,ratherthanthedefault<row>:
<EmployeeEmployeeID="4"FirstName="Rob"LastName="Walters"/>
<EmployeeEmployeeID="168"FirstName="Rob"MiddleName="T"LastName="Caron"/>
https://www.simpletalk.com/content/print.aspx?article=720
1/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
Inadditiontobeingabletoprovideanamefortherowelement,youcanalsospecifythatarootelementbecreatedtowrapallotherelements.Tocreatearootelement,addtheROOTkeywordtoyourFORXMLclause:
SELECTe.EmployeeID,c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLRAW('Employee'),ROOT
NoticethatyoumustincludeacommawhenaddinganoptionsuchasROOTinordertoseparatetheelements.Asthefollowingresultsshow,a<root>elementisnowincludedintheXML:
<root>
<EmployeeEmployeeID="4"FirstName="Rob"LastName="Walters"/>
<EmployeeEmployeeID="168"FirstName="Rob"MiddleName="T"LastName="Caron"/>
</root>
Aswiththerowelement,youcanalsoprovideaspecificnamefortherootelement:
SELECTe.EmployeeID,c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLRAW('Employee'),ROOT('Employees')
Inthiscase,Ivenamedtherootelement<Employees>,asshowninthefollowingresults:
<Employees>
<EmployeeEmployeeID="4"FirstName="Rob"LastName="Walters"/>
<EmployeeEmployeeID="168"FirstName="Rob"MiddleName="T"LastName="Caron"/>
</Employees>
Uptothispoint,theexamplesIveshownyouhaveaddedcolumnvaluesasattributestoeachrowelement.ThisisthedefaultbehavioroftheRAWmode.However,youcaninsteadspecifythatthecolumnvaluesbeaddedaschildelementstotherowelementby
includingtheELEMENTSoptionintheFORXMLclause:
SELECTe.EmployeeID,c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLRAW('Employee'),ROOT('Employees'),ELEMENTS
Onceagain,Iveaddedacommatoseparatetheoptions.Asyoucanseeinthefollowingresults,each<Employee>elementnowincludesasetofchildelementsthatcorrespondtothecolumnsreturnedbythequery:
<Employees>
<Employee>
<EmployeeID>4</EmployeeID>
<FirstName>Rob</FirstName>
<LastName>Walters</LastName>
</Employee>
<Employee>
<EmployeeID>168</EmployeeID>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</Employee>
</Employees>
Nowthe<Employee>elementsnolongerincludeanyattributesandalldataisrenderedthroughindividualchildelements.
https://www.simpletalk.com/content/print.aspx?article=720
2/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
IfyoureferbacktotheXMLreturnedbythepreviousexample,youllnoticethatthedataforemployee4(RobWalters)doesnotincludeamiddlename.ThisisbecausethatMiddleNamevalueisnullinthesourcedata,andbydefault,noelementsarecreatedfora
columnwhosevalueisnull.However,youcanoverridethisbehaviorbyaddingtheXSINILkeywordtotheELEMENTSoption:
SELECTe.EmployeeID,c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLRAW('Employee'),ROOT('Employees'),ELEMENTSXSINIL
NowtheresultswillincludeanelementfortheMiddleNamecolumnandwillincludethexsi:nilattributewithavalueoftruewhenavalueisnull,asshowninthefollowingXML:
<Employeesxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<Employee>
<EmployeeID>4</EmployeeID>
<FirstName>Rob</FirstName>
<MiddleNamexsi:nil="true"/>
<LastName>Walters</LastName>
</Employee>
<Employee>
<EmployeeID>168</EmployeeID>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</Employee>
</Employees>
Noticethatthexmlns:xsiattributehasalsobeenaddedtotherootnodeandprovidesthenameofthedefaultschemainstance.
AnotherimportantoptionthatissupportedbytheRAWnodeisXMLSCHEMA,whichspecifiesthataninlineW3CXMLSchema(XSD)beincludedintheXMLdata.YouaddtheXMLSCHEMAoptioninthesamewayyouaddotheroptions:
SELECTe.EmployeeID,c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLRAW('Employee'),ROOT('Employees'),ELEMENTSXSINIL,XMLSCHEMA
Asyoucanseeinthefollowingresults,theschemaisfullydefinedandisincorporatedintheXMLresults:
<Employeesxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<xsd:schematargetNamespace="urn:schemasmicrosoftcom:sql:SqlRowSet1"xmlns:xsd="http://www.w3.org/2001/XMLSchema"xmlns:sqltypes="http://schemas.microsoft.com/sqlserver/2004/sqltypes"
elementFormDefault="qualified">
<xsd:importnamespace="http://schemas.microsoft.com/sqlserver/2004/sqltypes"schemaLocation="http://schemas.microsoft.com/sqlserver/2004/sqltypes/sqltypes.xsd"/>
<xsd:elementname="Employee">
<xsd:complexType>
<xsd:sequence>
<xsd:elementname="EmployeeID"type="sqltypes:int"nillable="1"/>
<xsd:elementname="FirstName"nillable="1">
<xsd:simpleTypesqltypes:sqlTypeAlias="[AdventureWorks].[dbo].[Name]">
<xsd:restrictionbase="sqltypes:nvarchar"sqltypes:localeId="1033"sqltypes:sqlCompareOptions="IgnoreCaseIgnoreKanaTypeIgnoreWidth"sqltypes:sqlSortId="52">
<xsd:maxLengthvalue="50"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:elementname="MiddleName"nillable="1">
<xsd:simpleTypesqltypes:sqlTypeAlias="[AdventureWorks].[dbo].[Name]">
<xsd:restrictionbase="sqltypes:nvarchar"sqltypes:localeId="1033"sqltypes:sqlCompareOptions="IgnoreCaseIgnoreKanaTypeIgnoreWidth"sqltypes:sqlSortId="52">
<xsd:maxLengthvalue="50"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:elementname="LastName"nillable="1">
https://www.simpletalk.com/content/print.aspx?article=720
3/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
<xsd:simpleTypesqltypes:sqlTypeAlias="[AdventureWorks].[dbo].[Name]">
<xsd:restrictionbase="sqltypes:nvarchar"sqltypes:localeId="1033"sqltypes:sqlCompareOptions="IgnoreCaseIgnoreKanaTypeIgnoreWidth"sqltypes:sqlSortId="52">
<xsd:maxLengthvalue="50"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<Employeexmlns="urn:schemasmicrosoftcom:sql:SqlRowSet1">
<EmployeeID>4</EmployeeID>
<FirstName>Rob</FirstName>
<MiddleNamexsi:nil="true"/>
<LastName>Walters</LastName>
</Employee>
<Employeexmlns="urn:schemasmicrosoftcom:sql:SqlRowSet1">
<EmployeeID>168</EmployeeID>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</Employee>
</Employees>
Whenyouspecifythataschemabecreated,youcanalsospecifythenameofthetargetnamespace.Forexample,thefollowingFORXMLclauseincludestheXMLSCHEMAoption,followedbythenameofthetargetnamespace(urn:schema_example.com):
SELECTe.EmployeeID,c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLRAW('Employee'),ROOT('Employees'),ELEMENTSXSINIL,
XMLSCHEMA('urn:schema_example.com')
Thestatementwillreturnthesameresultsasthepreviousexample,exceptthattheXMLwillnowincludethenewnameofthetargetnamespace.
TheSELECTstatementsshownintheprecedingexampleshaveretrieveddatafromnonXMLcolumns(inthiscase,integerandstringcolumns).However,yourqueriesmightalsoretrievedatafromXMLcolumns.Insuchcases,theFORXMLclausewillincorporate
thedataretrievedfromanXMLcolumnintotheXMLresultset.
Forexample,thefollowingSELECTstatementusestheXMLquery()methodtoretrieveeducationrelateddatafromtheResumecolumnintheJobCandidatetable:
SELECTe.EmployeeID,c.FirstName,c.LastName,
jc.Resume.query('declarenamespacens=
"http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/Resume"
/ns:Resume/ns:Education')
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
INNERJOINHumanResources.JobCandidatejc
ONe.EmployeeID=jc.EmployeeID
WHEREe.EmployeeID=268
FORXMLRAW('Employee'),ELEMENTS
Thequery()methoditselfretrievesthefollowingdatafromtheResumecolumn:
<ns:Educationxmlns:ns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/Resume">
<ns:Edu.Level>Bachelor</ns:Edu.Level>
<ns:Edu.StartDate>19860915Z</ns:Edu.StartDate>
<ns:Edu.EndDate>19900520Z</ns:Edu.EndDate>
<ns:Edu.Degree>BachelorofArtsandScience</ns:Edu.Degree>
<ns:Edu.Major>Business</ns:Edu.Major>
<ns:Edu.Minor/>
<ns:Edu.GPA>3.3</ns:Edu.GPA>
https://www.simpletalk.com/content/print.aspx?article=720
4/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
<ns:Edu.GPAScale>4</ns:Edu.GPAScale>
<ns:Edu.School>LouisianaBusinessCollegeofNewOrleans</ns:Edu.School>
<ns:Edu.Location>
<ns:Location>
<ns:Loc.CountryRegion>US</ns:Loc.CountryRegion>
<ns:Loc.State>LA</ns:Loc.State>
<ns:Loc.City>NewOrleans</ns:Loc.City>
</ns:Location>
</ns:Edu.Location>
</ns:Education>
ThisdataisincorporatedintotherestoftheresultsetwhenyouusetheFORXMLclause,asshowninthefollowingresults:
<Employee>
<EmployeeID>268</EmployeeID>
<FirstName>Stephen</FirstName>
<LastName>Jiang</LastName>
<ns:Educationxmlns:ns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/Resume">
<ns:Edu.Level>Bachelor</ns:Edu.Level>
<ns:Edu.StartDate>19860915Z</ns:Edu.StartDate>
<ns:Edu.EndDate>19900520Z</ns:Edu.EndDate>
<ns:Edu.Degree>BachelorofArtsandScience</ns:Edu.Degree>
<ns:Edu.Major>Business</ns:Edu.Major>
<ns:Edu.Minor/>
<ns:Edu.GPA>3.3</ns:Edu.GPA>
<ns:Edu.GPAScale>4</ns:Edu.GPAScale>
<ns:Edu.School>LouisianaBusinessCollegeofNewOrleans</ns:Edu.School>
<ns:Edu.Location>
<ns:Location>
<ns:Loc.CountryRegion>US</ns:Loc.CountryRegion>
<ns:Loc.State>LA</ns:Loc.State>
<ns:Loc.City>NewOrleans</ns:Loc.City>
</ns:Location>
</ns:Edu.Location>
</ns:Education>
</Employee>
Asyoucansee,the<ns:Education>elementanditschildelementshavebeenaddedtotheXMLdata.ThenamespacedefinedonthesourcedataintheXMLcolumnisalsoincluded.
TheAUTOMode
TheAUTOmodeinaFORXMLclauseisslightlydifferentfromtheRAWmodeinthewaythatitgeneratestheXMLresultset.TheAUTOmodegeneratestheXMLbyusingheuristicsbasedonhowtheSELECTstatementisdefined.Thebestwaytounderstandhowthis
worksistolookatanexample.ThefollowingSELECTstatement,asinthepreviousexamples,retrievesemployeedatafromtheAdventureWorksdatabase:
SELECTEmployee.EmployeeID,ContactInfo.FirstName,
ContactInfo.MiddleName,ContactInfo.LastName
FROMHumanResources.EmployeeASEmployee
INNERJOINPerson.ContactASContactInfo
ONContactInfo.ContactID=Employee.ContactID
WHEREContactInfo.FirstName='Rob'
FORXMLAUTO,ROOT('Employees')
NoticethatIveprovidedmeaningfulaliasnamestothetables(EmployeeandContactinfo).ThesenamesareusedindefiningtheXMLelementnames,soyoullwanttoconstructyourSELECTstatementsaccordingly.Nowtakealookattheresultsreturnedbythis
query:
<Employees>
<EmployeeEmployeeID="4">
<ContactInfoFirstName="Rob"LastName="Walters"/>
</Employee>
<EmployeeEmployeeID="168">
https://www.simpletalk.com/content/print.aspx?article=720
5/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
<ContactInfoFirstName="Rob"MiddleName="T"LastName="Caron"/>
</Employee>
</Employees>
Asyoucansee,the<Employee>elementhasbeennamedautomaticallybasedonthetablealiasname.Noticetoothatthe<ContactInfo>elementisachildelementof<Employee>.Thestructureoftheelementsisbasedontheorderinwhichthecolumnsare
definedintheSELECTlistandthetablesthatarespecifiedintheFROMclause.Inthiscase,becauseEmployeeIDisthefirstcolumnintheSELECTlistandtheEmployeetableisincludedintheFROMclause,thefirstelementis<Employee>.Andbecausethe
remainingcolumns,whichareassociatedwiththeContactInfotable,appearnextintheSELECTlist,theyareaddedasachildelement.IfanadditionaltableanditscolumnswereincludedintheSELECTlist,aftertheothercolumns,theywouldappearasachild
elementof<ContactInfo>.
Inaddition,thecolumnsandtheirvaluesareaddedasattributestothetablerelatedelements.ThisstructureissimilartowhatyousawintheRAWmodeexamples.Andinthesameway,youcanoverridethedefaultbehaviorbyusingtheELEMENTSoption:
SELECTEmployee.EmployeeID,ContactInfo.FirstName,
ContactInfo.MiddleName,ContactInfo.LastName
FROMHumanResources.EmployeeASEmployee
INNERJOINPerson.ContactASContactInfo
ONContactInfo.ContactID=Employee.ContactID
WHEREContactInfo.FirstName='Rob'
FORXMLAUTO,ROOT('Employees'),ELEMENTS
AsyoucanseeinthefollowingXMLresultset,thecolumnvaluesarenowincludedaschildelements,ratherthanattributes:
<Employees>
<Employee>
<EmployeeID>4</EmployeeID>
<ContactInfo>
<FirstName>Rob</FirstName>
<LastName>Walters</LastName>
</ContactInfo>
</Employee>
<Employee>
<EmployeeID>168</EmployeeID>
<ContactInfo>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</ContactInfo>
</Employee>
</Employees>
Noticethatthe<ContactInfo>elementalsocontainschildelements,oneforeachcolumn.
Ifyouwanttoincludeanelementforcolumnswithnullvalues,youcanusetheXSINILoption,asyousawwhenusingtheRAWmode:
SELECTContactInfo.FirstName,ContactInfo.MiddleName,
ContactInfo.LastName,Employee.EmployeeID
FROMHumanResources.EmployeeASEmployee
INNERJOINPerson.ContactASContactInfo
ONContactInfo.ContactID=Employee.ContactID
WHEREContactInfo.FirstName='Rob'
FORXMLAUTO,ROOT('Employees'),ELEMENTSXSINIL
Nowtheresultswillincludeallelements.Thatmeans,ifavalueisnull,thexsi:nilattributeisincluded:
<Employeesxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<ContactInfo>
<FirstName>Rob</FirstName>
<MiddleNamexsi:nil="true"/>
<LastName>Walters</LastName>
<Employee>
<EmployeeID>4</EmployeeID>
https://www.simpletalk.com/content/print.aspx?article=720
6/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
</Employee>
</ContactInfo>
<ContactInfo>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
<Employee>
<EmployeeID>168</EmployeeID>
</Employee>
</ContactInfo>
</Employees>
Asyouveseenintheseexamples,theXMLisbasedonhowthecolumnsarelistedintheSELECTlist.However,asImentionedearlier,theXMLisalsobasedonthetableslistedintheFROMclause.Intheprecedingexamples,theSELECTlistcontainedonly
columnsthatarereferencedintheFROMclause.IfacolumnisnotdirectlyassociatedwithatableintheFROMclause(asinacomputedoraggregatecolumn),thecolumnisnestedatthedeepestlevelwhereveritappears.
Forexample,thefollowingSELECTstatementincludestheFullNamecomputedcolumn,whichconcatenatesthefirstandlastnames:
SELECTEmployee.EmployeeID,
(ContactInfo.FirstName+''+ContactInfo.LastName)ASFullName,
ContactInfo.EmailAddress
FROMHumanResources.EmployeeASEmployee
INNERJOINPerson.ContactASContactInfo
ONContactInfo.ContactID=Employee.ContactID
WHEREContactInfo.FirstName='Rob'
FORXMLAUTO,ROOT('Employees'),ELEMENTSXSINIL
BecausetheFullNamecolumnappearsintheSELECTlistaftertheEmployeeIDcolumn,theFullNamecolumnisaddedasachildelementof<Employee>,asshowninthefollowingXML:
<Employeesxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<Employee>
<EmployeeID>4</EmployeeID>
<FullName>RobWalters</FullName>
<ContactInfo>
<EmailAddress>rob0@adventureworks.com</EmailAddress>
</ContactInfo>
</Employee>
<Employee>
<EmployeeID>168</EmployeeID>
<FullName>RobCaron</FullName>
<ContactInfo>
<EmailAddress>rob1@adventureworks.com</EmailAddress>
</ContactInfo>
</Employee>
</Employees>
AsIvementioned,theplacementofcolumnsintheSELECTlistimpactstheresultingXML.Thisisalsothecasewithcomputedcolumns.Forexample,inthefollowingSELECTstatement,IveaddedtheFullNamecolumnaftertheEmailAddresscolumn:
SELECTEmployee.EmployeeID,ContactInfo.EmailAddress,
(ContactInfo.FirstName+''+ContactInfo.LastName)ASFullName
FROMHumanResources.EmployeeASEmployee
INNERJOINPerson.ContactASContactInfo
ONContactInfo.ContactID=Employee.ContactID
WHEREContactInfo.FirstName='Rob'
FORXMLAUTO,ROOT('Employees'),ELEMENTSXSINIL
NowtheFullNamecolumnwillbeaddedasachildelementtothe<ContactInfo>element,asthefollowingXMLdemonstrates.
<Employeesxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<Employee>
<EmployeeID>4</EmployeeID>
https://www.simpletalk.com/content/print.aspx?article=720
7/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
<ContactInfo>
<EmailAddress>rob0@adventureworks.com</EmailAddress>
<FullName>RobWalters</FullName>
</ContactInfo>
</Employee>
<Employee>
<EmployeeID>168</EmployeeID>
<ContactInfo>
<EmailAddress>rob1@adventureworks.com</EmailAddress>
<FullName>RobCaron</FullName>
</ContactInfo>
</Employee>
</Employees>
Astheseresultsshow,youmustbeawareoftheorderyouplacecolumnswhenyoudefineyourSELECTlist.
NowletstakealookatanotheraspectoftheAUTOmode.Oneofthelimitationsofthismode(aswellastheRAWmode)isthatthecolumndataisaddedaseitherattributesorchildelements,dependingonwhetheryouspecifytheELEMENTSoption.However,there
mightbetimeswhenyouwanttoreturnsomeofthedataasattributesandsomeaschildelements.OnemethodyoucanusewiththeAUTOmodeistoreturnsomeofthedatainasubquery.Forexample,thefollowingSELECTstatementincludesasubquerythat
returnstheemployeesfirstandlastnames:
SELECTEmployeeID,LoginID,
(SELECTFirstName,LastName
FROMPerson.ContactASEmployeeName
WHEREEmployeeName.ContactID=Employee.ContactID
FORXMLAUTO,TYPE,ELEMENTS)
FROMHumanResources.EmployeeASEmployee
WHEREEmployeeID=168
FORXMLAUTO
NoticethatthesubqueryincludesaFORXMLclausethatusesAUTOmodeandincludestheELEMENTSoption.TheFORXMLclausealsoincludestheTYPEoption,whichspecifiesthatthedatareturnedbythesubquerybereturnedastheXMLtype.Youmust
includetheTYPEoptiontopreservethedataasXMLintheouterSELECTstatement.
TheouterSELECTstatementalsoincludesaFORXMLclause,buttheELEMENTSoptionisnotincluded.Asaresult,onlythefirstandlastnameswillbereturnedaschildelements,buttheemployeeIDandloginIDwillbereturnedasattributes,asshowninthe
followingXML:
<EmployeeEmployeeID="168"LoginID="adventureworks\rob1">
<EmployeeName>
<FirstName>Rob</FirstName>
<LastName>Caron</LastName>
</EmployeeName>
</Employee>
Asyoucansee,subqueriesletyoumaintainsomecontrolovertheoutput.However,theAUTOmode(andtheRAWmode,forthatmatter)provideslittlecontrolovertheXMLreturnedbyyourquery.Forgreatercontrol,youllwanttousetheEXPLICITmodeorthe
PATHmode.
TheEXPLICITMode
TheEXPLICITmodeprovidesveryspecificcontroloveryourXML,butthismodeismuchmorecomplextousethantheRAWorAUTOmodes.Tousethismode,youmustbuildyourSELECTstatementsinsuchaswayastodefinetheXMLhierarchyandstructure.In
addition,youmustcreateaSELECTstatementforeachlevelofthathierarchyanduseUNIONALLclausestojointhosestatements.
ThereareanumberofrulesthatdescribehowtodefineyourSELECTstatementswhenusingtheEXPLICITmode,anditisbeyondthescopeofthisarticletoreviewallthoserules,sobesuretorefertothetopicUsingEXPLICITModeinSQLServerBooksOnline
forthedetailsabouthowtoconstructyourSELECTstatements.Inthemeantime,letstakealookatafewexamplesthathelpdemonstratesomeofthebasicelementsoftheEXPLICITmode.
WhenconstructingyourSELECTstatement,youmustincludetwocolumnsinyourSELECTlistthatdescribetheXMLhierarchy.Thefirstcolumn,Tag,isassignedanumericalvalueforeachlevelofthehierarchy.Forinstance,thefirstSELECTstatementshould
includeaTagcolumnwithavalueof1.Thisisthetoplevelofthehierarchy.ThesecondSELECTstatementshouldincludeaTagcolumnwithavalueof2,andsoon.
ThesecondcolumnthatyoushouldincludeinyourSELECTstatementisParent.Again,thisisanumericalvaluethatidentifiestheparentofthehierarchybasedontheTagvaluesyouveassigned.InthefirstSELECTstatement,theParentvalueshouldbenullto
indicatethatthisisatoplevelhierarchy.
YourfirstSELECTstatementshouldalsoincludeareferencetoallthecolumnsthatwillmakeuptheXMLstructure.Thecolumnsmustalsoincludealiasesthatdefinethatstructure.Letslookatanexampletohelpunderstandhowthisallworks.Thefollowing
https://www.simpletalk.com/content/print.aspx?article=720
8/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
SELECTstatementsreturnresultssimilartowhatyouveseeninpreviousexampleshowever,theSELECTstatementsthemselvesaremoredetailed:
SELECT1ASTag,
NULLASParent,
e.EmployeeIDAS[Employee!1!EmployeeID],
NULLAS[ContactInfo!2!FirstName!ELEMENT],
NULLAS[ContactInfo!2!MiddleName!ELEMENT],
NULLAS[ContactInfo!2!LastName!ELEMENT]
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
UNIONALL
SELECT2ASTag,
1ASParent,
e.EmployeeID,
c.FirstName,
c.MiddleName,
c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONe.ContactID=c.ContactID
WHEREc.FirstName='Rob'
ORDERBY[Employee!1!EmployeeID],[ContactInfo!2!FirstName!ELEMENT]
FORXMLEXPLICIT
InthefirstSELECTstatement,IbeginbydefiningtheTagcolumnandassigningavalueof1tothatcolumn.NextIdefinetheParentcolumnandassignanullvalue.IthendefinetheEmployeeIDcolumnandassignanaliastothatcolumn.NoticethatIuseavery
specificstructuretodefinethealiasname:
<ElementName>!<TagNumber>!<AttributeName>[!<OptionalDirective>]
Asthesyntaxshows,thefirstthreecomponentsarerequired,andthelastisoptional:
<ElementName>:Thenameoftheelementthatthevalueshouldbeassignedto.
<TagNumber>:Thetagnumberassociatedwiththehierarchythatthevalueshouldbeassignedto,asdefinedintheTagcolumn.
<AttributeName>:Thenameoftheattributeassociatedwiththecolumnvalue,unlessanoptionaldirectiveisspecified.Forexample,iftheELEMENTdirectiveisspecified,<AttributeName>isthenameofthechildelement.
<OptionalDirective>:AdditionalinformationforhowtoconstructtheXML.
Forexample,basedonthealiasnameassignedtotheEmployeeIDcolumn,youcanseethattheEmployeeIDattributewillbeassociatedwiththe<Employee>elementonthefirstlevelofthehierarchy.
BecausethenextthreecolumnsintheSELECTlistareassociatedwiththesecondleveloftheXMLhierarchy,whichisdefinedinthesecondSELECTstatement,nullvaluesareassignedtothealiasnamesforthecolumn.ThiswillprovidetheXMLstructure
necessarytojointhetwoSELECTstatements.
ThesecondSELECTstatementismuchsimpler,butitstillincludestheTagandParentcolumnsintheSELECTlist.TheremainingcolumnsintheSELECTlistaredefinedasyouwouldnormallydefinecolumnsinyourquery.
TheresultsetforthetwoSELECTstatementsisthenorderedbytheEmployeeIDandFirstNamecolumns.ThisisnecessarysothatnullvaluesappearfirstintheresultsettoensurethattheXMLisproperlyformatted.TheFORXMLclauseisthenappendedtothe
endoftheSELECTstatementinordertogeneratethefollowingXML:
<EmployeeEmployeeID="4">
<ContactInfo>
<FirstName>Rob</FirstName>
<LastName>Walters</LastName>
</ContactInfo>
</Employee>
<EmployeeEmployeeID="168">
<ContactInfo>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</ContactInfo>
</Employee>
https://www.simpletalk.com/content/print.aspx?article=720
9/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
TheEmployeeIDcolumnhasnowbeenaddedasanattributetothe<Employee>element.However,youcanchangetheEmployeeIDcolumntoachildelementsimplybyaddingtheELEMENTdirective,asIdidwiththeothercolumns:
SELECT1ASTag,
NULLASParent,
e.EmployeeIDAS[Employee!1!EmployeeID!ELEMENT],
NULLAS[ContactInfo!2!FirstName!ELEMENT],
NULLAS[ContactInfo!2!MiddleName!ELEMENT],
NULLAS[ContactInfo!2!LastName!ELEMENT]
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
UNIONALL
SELECT2ASTag,
1ASParent,
e.EmployeeID,
c.FirstName,
c.MiddleName,
c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONe.ContactID=c.ContactID
WHEREc.FirstName='Rob'
ORDERBY[Employee!1!EmployeeID!ELEMENT],[ContactInfo!2!FirstName!ELEMENT]
FORXMLEXPLICIT
NowtheEmployeeIDvaluewillbedisplayedasachildelementof<Employee>,thefirstlevelelement:
<Employee>
<EmployeeID>4</EmployeeID>
<ContactInfo>
<FirstName>Rob</FirstName>
<LastName>Walters</LastName>
</ContactInfo>
</Employee>
<Employee>
<EmployeeID>168</EmployeeID>
<ContactInfo>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</ContactInfo>
</Employee>
YoucanalsoensurethatcolumnswithnullvalueswillstilldisplaytheelementbychangingtheELEMENTSdirectivetoELEMENTSXSINIL,asshowninthefollowingSELECTstatement:
SELECT1ASTag,
NULLASParent,
e.EmployeeIDAS[Employee!1!EmployeeID!ELEMENT],
NULLAS[ContactInfo!2!FirstName!ELEMENT],
NULLAS[ContactInfo!2!MiddleName!ELEMENTXSINIL],
NULLAS[ContactInfo!2!LastName!ELEMENT]
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
UNIONALL
SELECT2ASTag,
1ASParent,
e.EmployeeID,
c.FirstName,
c.MiddleName,
c.LastName
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONe.ContactID=c.ContactID
https://www.simpletalk.com/content/print.aspx?article=720
10/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
WHEREc.FirstName='Rob'
ORDERBY[Employee!1!EmployeeID!ELEMENT],[ContactInfo!2!FirstName!ELEMENT]
FORXMLEXPLICIT
Nowtheresultswillincludethexsi:nilattributewherevaluesarenullintheMiddleNamecolumn,asshowninthefollowingXML:
<Employeexmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<EmployeeID>4</EmployeeID>
<ContactInfo>
<FirstName>Rob</FirstName>
<MiddleNamexsi:nil="true"/>
<LastName>Walters</LastName>
</ContactInfo>
</Employee>
<Employeexmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<EmployeeID>168</EmployeeID>
<ContactInfo>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</ContactInfo>
</Employee>
Asyoucanseefromtheseexamples,theEXPLICITmodecancauseyourSELECTstatementstobecomequitecomplex,especiallyifyouwanttoaddmorelevelstothehierarchyorwanttocreatemoreintricateSELECTstatements.Fortunately,mostofwhatyou
candowiththeEXPLICITmode,youcandowiththePATHmode,anddoitinamuchsimplerway.
ThePATHMode
WhenyouspecifythePATHmodeintheFORXMLclause,columnnames(ortheiraliases)aretreatedasXPathexpressionsthatdeterminehowthedatavalueswillbemappedtotheXMLresultset.Bydefault,XMLelementsaredefinedbasedoncolumnnames.
Youcanmodifythedefaultbehaviorbyusingtheat(@)symboltodefineattributesortheforwardslash(/)todefinethehierarchy.Letstakealookatafewexamplestodemonstratehowallthisworks.
WellbeginwiththePATHmodesdefaultbehavior.ThefollowingexampleincludesaFORXMLclausethatspecifiesonlythePATHoption:
SELECTe.EmployeeID,c.FirstName,
c.MiddleName,c.LastName
FROMHumanResources.EmployeeASe
INNERJOINPerson.ContactASc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLPATH
Becausenospecificattributesorhierarchieshavebeendefined,thequerywillreturnthefollowingXML:
<row>
<EmployeeID>4</EmployeeID>
<FirstName>Rob</FirstName>
<LastName>Walters</LastName>
</row>
<row>
<EmployeeID>168</EmployeeID>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</row>
Asyoucansee,eachcolumnisaddedasachildelementtothe<row>element.YoudonothavetospecifytheELEMENTSdirectivebecauseindividualelementsarereturnedbydefault,basedonthecolumnnames.
Youcanalsorenametherowelementanddefinearootelement,asyouveseeninearlierexamples:
https://www.simpletalk.com/content/print.aspx?article=720
11/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
SELECTe.EmployeeID,c.FirstName,
c.MiddleName,c.LastName
FROMHumanResources.EmployeeASe
INNERJOINPerson.ContactASc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLPATH('Employee'),ROOT('Employees')
Asthefollowingresultsshow,theXMLnowincludesthe<Employees>rootelementandtheindividual<Employee>rowelements:
<Employees>
<Employee>
<EmployeeID>4</EmployeeID>
<FirstName>Rob</FirstName>
<LastName>Walters</LastName>
</Employee>
<Employee>
<EmployeeID>168</EmployeeID>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</Employee>
</Employees>
Suppose,now,thatyouwanttoincludetheEmployeeIDvalueasanattributeof<Employee>.YoucaneasilydothisbyaddinganaliastotheEmployeeIDcolumnintheSELECTclauseandprecedingthealiasnamewith@,asshowninthefollowingexample:
SELECTe.EmployeeIDAS"@EmpID",
c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeASe
INNERJOINPerson.ContactASc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLPATH('Employee'),ROOT('Employees')
Nowthe<Employee>elementscontaintheEmpIDattribute,alongwiththeemployeeID:
<Employees>
<EmployeeEmpID="4">
<FirstName>Rob</FirstName>
<LastName>Walters</LastName>
</Employee>
<EmployeeEmpID="168">
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</Employee>
</Employees>
YoucanseehoweasyitistoreturnbothattributesandchildelementsbyusingthePATHmode.Andifyouwanttoincludeelementswithnullvalues,yousimplyincludetheELEMENTSXSINILoptioninyourFORXMLclause:
SELECTe.EmployeeIDAS"@EmpID",
c.FirstName,c.MiddleName,c.LastName
FROMHumanResources.EmployeeASe
INNERJOINPerson.ContactASc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLPATH('Employee'),ROOT('Employees'),ELEMENTSXSINIL
https://www.simpletalk.com/content/print.aspx?article=720
12/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
Nowyourresultsincludethexsi:nilattributeforthosefieldsthatcontainnullvalues:
<Employeesxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<EmployeeEmpID="4">
<FirstName>Rob</FirstName>
<MiddleNamexsi:nil="true"/>
<LastName>Walters</LastName>
</Employee>
<EmployeeEmpID="168">
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</Employee>
</Employees>
Asyoucansee,thexsi:nilattributeinthe<MiddleName>elementhasbeensettotrue.
Note:BecausethePATHmodeautomaticallyreturnsvaluesasindividualchildelements,theELEMENTSdirectivehasnoeffectwhenusedbyitselfinaFORXMLclause.ItisonlywhentheXSINILoptionisalsospecifiedthattheELEMENTSdirectiveadds
valuetotheclause.
InadditiontodefiningattributeswithinyourcolumnaliasesintheSELECTlist,youcanalsodefinehierarchies.Youdefinehierarchiesbyusingtheforwardslashandspecifyingtheelementnames.Forexample,thefollowingSELECTdefinesthe<EmployeeName>
elementanditsthreechildelements:<FirstName>,<MiddleName>,and<LastName>:
SELECTe.EmployeeIDAS"@EmpID",
c.FirstNameAS"EmployeeName/FirstName",
c.MiddleNameAS"EmployeeName/MiddleName",
c.LastNameAS"EmployeeName/LastName"
FROMHumanResources.EmployeeASe
INNERJOINPerson.ContactASc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLPATH('Employee'),ROOT('Employees'),ELEMENTSXSINIL
ThestatementreturnsthefollowingXMLresultset:
<Employeesxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<EmployeeEmpID="4">
<EmployeeName>
<FirstName>Rob</FirstName>
<MiddleNamexsi:nil="true"/>
<LastName>Walters</LastName>
</EmployeeName>
</Employee>
<EmployeeEmpID="168">
<EmployeeName>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</EmployeeName>
</Employee>
</Employees>
Noticethateach<Employee>elementnowincludesan<EmployeeName>element,andeachofthoseelementsincludestheindividualpartsofthename.
Supposethatyounowwanttoaddanemailaddresstoyourresultset.YoucansimplyaddthecolumntotheSELECTlistaftertheothercolumns,asshowninthefollowingexample:
SELECTe.EmployeeIDAS"@EmpID",
c.FirstNameAS"EmployeeName/FirstName",
c.MiddleNameAS"EmployeeName/MiddleName",
https://www.simpletalk.com/content/print.aspx?article=720
13/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
c.LastNameAS"EmployeeName/LastName",
c.EmailAddress
FROMHumanResources.EmployeeASe
INNERJOINPerson.ContactASc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLPATH('Employee'),ROOT('Employees'),ELEMENTSXSINIL
BecausethecolumnnameisEmailAddressandnoaliashasbeendefinedonthatcolumn,yourXMLresultswillnowincludethe<EmailAddress>elementasachildelementto<Employee>,rightafter<EmployeeName>:
<Employeesxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<EmployeeEmpID="4">
<EmployeeName>
<FirstName>Rob</FirstName>
<MiddleNamexsi:nil="true"/>
<LastName>Walters</LastName>
</EmployeeName>
<EmailAddress>rob0@adventureworks.com</EmailAddress>
</Employee>
<EmployeeEmpID="168">
<EmployeeName>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
<LastName>Caron</LastName>
</EmployeeName>
<EmailAddress>rob1@adventureworks.com</EmailAddress>
</Employee>
</Employees>
YoumustbecarefulonhowyouorderyourcolumnsintheSELECTlist.Forexample,inthefollowingSELECTstatement,IaddedtheEmailAddresscolumnafterMiddleName,butbeforeLastName:
SELECTe.EmployeeIDAS"@EmpID",
c.FirstNameAS"EmployeeName/FirstName",
c.MiddleNameAS"EmployeeName/MiddleName",
c.EmailAddress,
c.LastNameAS"EmployeeName/LastName"
FROMHumanResources.EmployeeASe
INNERJOINPerson.ContactASc
ONc.ContactID=e.ContactID
WHEREc.FirstName='Rob'
FORXMLPATH('Employee'),ROOT('Employees'),ELEMENTSXSINIL
BecauseIdonotlistthepartsoftheemployeenamesconsecutively,theyareseparatedintheXMLresults:
<Employeesxmlns:xsi="http://www.w3.org/2001/XMLSchemainstance">
<EmployeeEmpID="4">
<EmployeeName>
<FirstName>Rob</FirstName>
<MiddleNamexsi:nil="true"/>
</EmployeeName>
<EmailAddress>rob0@adventureworks.com</EmailAddress>
<EmployeeName>
<LastName>Walters</LastName>
</EmployeeName>
</Employee>
<EmployeeEmpID="168">
<EmployeeName>
<FirstName>Rob</FirstName>
<MiddleName>T</MiddleName>
</EmployeeName>
<EmailAddress>rob1@adventureworks.com</EmailAddress>
https://www.simpletalk.com/content/print.aspx?article=720
14/15
3/6/2015
Printpreview:UsingtheFORXMLClausetoReturnQueryResultsasXML
<EmployeeName>
<LastName>Caron</LastName>
</EmployeeName>
</Employee>
</Employees>
AstheXMLshows,therearenowtwoinstancesofthe<EmployeeName>childelementineach<Employee>element.ThewaytoaddressthisissueistomakecertainyoulistthecolumnsinyourSELECTlistintheorderyouwanttheXMLrendered.
Inanearlierexample,IdemonstratedhowtoincludeanXMLcolumninyourquery.YoucanalsoincludeanXMLcolumnwhenusingthePATHmode.TheXMLdatareturnedbythecolumnisincorporatedintotheXMLthatisreturnedbythequery.Forinstance,the
followingSELECTstatementaddseducationdatatotheresultset:
SELECTe.EmployeeIDAS"@EmpID",
c.FirstNameAS"EmployeeName/FirstName",
c.MiddleNameAS"EmployeeName/MiddleName",
c.LastNameAS"EmployeeName/LastName",
c.EmailAddress,
jc.Resume.query('declarenamespacens=
"http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/Resume"
/ns:Resume/ns:Education')
FROMHumanResources.EmployeeeINNERJOINPerson.Contactc
ONc.ContactID=e.ContactID
INNERJOINHumanResources.JobCandidatejc
ONe.EmployeeID=jc.EmployeeID
WHEREe.EmployeeID=268
FORXMLPATH('Employee')
The<Education>elementandchildelementsarenowincludedtheXMLresultset:
<EmployeeEmpID="268">
<EmployeeName>
<FirstName>Stephen</FirstName>
<MiddleName>Y</MiddleName>
<LastName>Jiang</LastName>
</EmployeeName>
<EmailAddress>stephen0@adventureworks.com</EmailAddress>
<ns:Educationxmlns:ns="http://schemas.microsoft.com/sqlserver/2004/07/adventureworks/Resume">
<ns:Edu.Level>Bachelor</ns:Edu.Level>
<ns:Edu.StartDate>19860915Z</ns:Edu.StartDate>
<ns:Edu.EndDate>19900520Z</ns:Edu.EndDate>
<ns:Edu.Degree>BachelorofArtsandScience</ns:Edu.Degree>
<ns:Edu.Major>Business</ns:Edu.Major>
<ns:Edu.Minor/>
<ns:Edu.GPA>3.3</ns:Edu.GPA>
<ns:Edu.GPAScale>4</ns:Edu.GPAScale>
<ns:Edu.School>LouisianaBusinessCollegeofNewOrleans</ns:Edu.School>
<ns:Edu.Location>
<ns:Location>
<ns:Loc.CountryRegion>US</ns:Loc.CountryRegion>
<ns:Loc.State>LA</ns:Loc.State>
<ns:Loc.City>NewOrleans</ns:Loc.City>
</ns:Location>
</ns:Edu.Location>
</ns:Education>
</Employee>
Astheseprecedingexamplesdemonstrate,thePATHmodeprovidesarelativelyeasywaytodefineelementsandattributesinyourXMLresultset.However,thePATHmode,liketheotherFORXMLmodes,supportsadditionaloptions.Forthatreason,besureto
checkoutSQLServerBooksOnlineformoreinformationabouteachmodeandabouttheFORXMLclauseingeneral.Despitehowbasictheclauseitselfmightseem,itprovidesnumerousoptionsforreturningexactlythetypeofXMLdatayouneed.
SimpleTalk.com
https://www.simpletalk.com/content/print.aspx?article=720
15/15