Utilizzo della modalità PATH
Come descritto nell'argomento relativo alla costruzione di XML tramite FOR XML, la modalità PATH consente di combinare in modo più semplice elementi e attributi e di introdurre nidificazione aggiuntiva per la rappresentazione di proprietà complesse. È possibile utilizzare query in modalità FOR XML EXPLICIT per la costruzione di questo tipo di strutture XML da un set di righe, ma la modalità PATH costituisce un'alternativa più semplice alla formulazione di query in modalità EXPLICIT, che può essere un'operazione complessa. La modalità PATH, combinata alla possibilità di scrivere query FOR XML nidificate e alla direttiva TYPE per la restituzione di istanze di tipo xml, consente la scrittura di query meno complesse.
In modalità PATH i nomi e gli alias di colonna vengono gestiti come espressioni XPath. Queste espressioni indicano il modo in cui viene eseguito il mapping tra i valori e il codice XML. Ogni espressione XPath è un XPath relativo che specifica il tipo dell'elemento, ad esempio attributo, elemento e valore scalare, nonché il nome e la gerarchia del nodo che verrà generato in relazione all'elemento riga.
In questo argomento vengono descritte le condizioni seguenti per eseguire il mapping delle colonne in un set di righe:
- Colonne senza nome
- Colonne provviste di un nome
- Colonne con nome specificato come carattere jolly (*)
- Colonne con il nome di un test di nodo XPath
- Nomi di colonna con il percorso specificato come data()
- Colonne contenenti un valore NULL per impostazione predefinita
Colonne senza nome
Qualsiasi colonna priva di nome verrà resa inline. Ad esempio, le colonne calcolate o le query scalari nidificate che non specificano un alias di colonna genereranno colonne senza nome. Se la colonna è di tipo xml, viene inserito il contenuto dell'istanza di quel tipo di dati. In caso contrario, il contenuto della colonna viene inserito come nodo di testo.
SELECT 2+2
FOR XML PATH
Produrre questo codice XML. Per impostazione predefinita, per ogni riga del set di righe viene generato un elemento <row
> nel codice XML risultante, come avviene in modalità RAW.
<row>4</row>
La query seguente restituisce un set di righe a tre colonne. La terza colonna priva di nome contiene dati XML. La modalità PATH inserisce un'istanza del tipo XML.
SELECT ProductModelID,
Name,
Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
/MI:root/MI:Location
')
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH
go
Risultato parziale:
<row>
<ProductModelID>7</ProductModelID>
<Name>HL Touring Frame</Name>
<MI:Location ...LocationID="10" ...></MI:Location>
<MI:Location ...LocationID="20" ...></MI:Location>
...
</row>
Colonne provviste di un nome
Di seguito sono illustrate le condizioni specifiche in cui viene eseguito il mapping tra le colonne del set di righe provviste di nome e il codice XML risultante, con distinzione tra maiuscole e minuscole:
- Il nome di colonna inizia con un simbolo di chiocciola (@)
- Il nome di colonna non inizia con un simbolo di chiocciola (@)
- Il nome di colonna non inizia con un simbolo di chiocciola (@) e contiene una barra (/)
- Più colonne condividono lo stesso prefisso
- Una colonna ha un nome diverso
Il nome di colonna inizia con un simbolo di chiocciola (@)
Se il nome della colonna inizia con un simbolo di chiocciola e non contiene una barra (/), viene creato un attributo dell'elemento <row
> con il valore di colonna corrispondente. Ad esempio, la query seguente resituisce un set di righe a due colonne (@PmId, Name). Nel codice XML risultante, un attributo PmId viene aggiunto all'elemento <row
> corrispondente e gli viene assegnato un valore di ProductModelID.
SELECT ProductModelID as "@PmId",
Name
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH
go
Risultato:
<row PmId="7">
<Name>HL Touring Frame</Name>
</row>
Si noti che gli attributi devono precedere qualsiasi altro tipo di nodo presente nello stesso livello, ad esempio nodi di elemento e di testo. La query seguente restituirà un errore:
SELECT Name,
ProductModelID as "@PmId"
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH
go
Il nome di colonna non inizia con un simbolo di chiocciola (@)
Se il nome di colonna non inizia con un simbolo di chiocciola (@), non è uno dei test di nodo XPath e non contiene una barra (/), viene creato un elemento XML che è un sottoelemento dell'elemento riga, per impostazione predefinita <row
>.
La query seguente specifica il nome della colonna, il risultato. Un elemento figlio <result
> viene pertanto aggiunto all'elemento <row
>.
SELECT 2+2 as result
for xml PATH
Risultato:
<row>
<result>4</result>
</row>
La query seguente specifica il nome della colonna, ManuWorkCenterInformation, per il codice XML restituito dall'espressione XQuery specificata sulla colonna Instructions di tipo xml. Un elemento <ManuWorkCenterInformation
> viene pertanto aggiunto come figlio dell'elemento <row
>.
SELECT
ProductModelID,
Name,
Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
/MI:root/MI:Location
') as ManuWorkCenterInformation
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH
go
Risultato:
<row>
<ProductModelID>7</ProductModelID>
<Name>HL Touring Frame</Name>
<ManuWorkCenterInformation>
<MI:Location ...LocationID="10" ...></MI:Location>
<MI:Location ...LocationID="20" ...></MI:Location>
...
</ManuWorkCenterInformation>
</row>
Il nome di colonna non inizia con un simbolo di chiocciola (@) e contiene una barra (/)
Se il nome di colonna non inizia con un simbolo di chiocciola (@), ma contiene una barra(/), il nome della colonna indica una gerarchia XML. Ad esempio, se il nome della colonna è "Name1/Name2/Name3.../Namen ", ogni Namei rappresenta un nome elemento annidato nell'elemento di riga corrente (per i=1) o che si trova sotto l'elemento il cui nome è Namei-1. Se Namen inizia con il simbolo @, viene mappato a un attributo dell'elemento Namen-1.
Ad esempio, la query seguente restituisce l'ID e il nome di un dipendente rappresentati come un elemento complesso EmpName che contiene nome, secondo nome e cognome.
SELECT EmployeeID "@EmpID",
FirstName "EmpName/First",
MiddleName "EmpName/Middle",
LastName "EmpName/Last"
FROM HumanResources.Employee E, Person.Contact C
WHERE E.EmployeeID = C.ContactID
AND E.EmployeeID=1
FOR XML PATH
I nomi di colonna vengono usati come un percorso nella creazione del codice XML in modalità PATH. Il nome della colonna che contiene i valori ID dipendente inizia con il simbolo @. Un attributo EmpID viene pertanto aggiunto all'elemento <row
>. I nomi di tutte le altre colonne contengono una barra ("/"), che indica la gerarchia. Il codice XML risultante avrà l'elemento figlio <EmpName
> sotto l'elemento <row
> e l'elemento figlio <EmpName
> avrà gli elementi figlio <First
>, <Middle
> e <Last
>.
<row EmpID="1">
<EmpName>
<First>Gustavo</First>
<Last>Achong</Last>
</EmpName>
</row>
Il valore del secondo nome del dipendente è Null e, per impostazione predefinita, il valore Null corrisponde all'assenza dell'elemento o attributo. Se si desidera la generazione di elementi per i valori NULL, è possibile specificare la direttiva ELEMENTS con XSINIL, come illustrato in questa query.
SELECT EmployeeID "@EmpID",
FirstName "EmpName/First",
MiddleName "EmpName/Middle",
LastName "EmpName/Last"
FROM HumanResources.Employee E, Person.Contact C
WHERE E.EmployeeID = C.ContactID
AND E.EmployeeID=1
FOR XML PATH, ELEMENTS XSINIL
Risultato:
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
EmpID="1">
<EmpName>
<First>Gustavo</First>
<Middle xsi:nil="true" />
<Last>Achong</Last>
</EmpName>
</row>
Per impostazione predefinita, la modalità PATH genera XML incentrato sugli elementi. Specificare la direttiva ELEMENTS in una query in modalità PATH pertanto non produce effetti. Come illustrato nell'esempio precedente tuttavia, la direttiva ELEMENTS risulta utile con XSINIL per la generazione di elementi per i valori Null.
Oltre all'ID e al nome, la query seguente recupera l'indirizzo di un dipendente. Come per il percorso nei nomi di colonna per le colonne degli indirizzi, un elemento figlio <Address
> viene aggiunto all'elemento <row
> e i dettagli relativi agli indirizzi vengono aggiunti come elementi figlio dell'elemento <Address
>.
SELECT EmployeeID "@EmpID",
FirstName "EmpName/First",
MiddleName "EmpName/Middle",
LastName "EmpName/Last",
AddressLine1 "Address/AddrLine1",
AddressLine2 "Address/AddrLIne2",
City "Address/City"
FROM HumanResources.Employee E, Person.Contact C, Person.Address A
WHERE E.EmployeeID = C.ContactID
AND E.AddressID = A.AddressID
AND E.EmployeeID=1
FOR XML PATH
Risultato:
<row EmpID="1">
<EmpName>
<First>Gustavo</First>
<Last>Achong</Last>
</EmpName>
<Address>
<AddrLine1>7726 Driftwood Drive</AddrLine1>
<City>Monroe</City>
</Address>
</row>
Più colonne condividono lo stesso prefisso di percorso
Se più colonne successive condividono lo stesso prefisso di percorso, vengono raggruppate sotto lo stesso nome. Se vengono utilizzati prefissi degli spazi dei nomi diversi, anche se associati allo stesso spazio dei nomi, un percorso viene considerato diverso. Nella query precedente, le colonne FirstName, MiddleName e LastName condividono lo stesso prefisso EmpName. Vengono pertanto aggiunte come elementi figlio dell'elemento <EmpName
>. Ciò si verifica anche nell'esempio precedente, nella fase di creazione dell'elemento <Address
>.
Una colonna ha un nome diverso
Se è presente una colonna con un nome diverso, interromperà il raggruppamento, come illustrato nella query modificata seguente. La query interrompe il raggruppamento di FirstName, MiddleName e LastName, come specificato nella query precedente, aggiungendo colonne di indirizzi fra le colonne FirstName e MiddleName.
SELECT EmployeeID "@EmpID",
FirstName "EmpName/First",
AddressLine1 "Address/AddrLine1",
AddressLine2 "Address/AddrLIne2",
City "Address/City",
MiddleName "EmpName/Middle",
LastName "EmpName/Last"
FROM HumanResources.EmployeeAddress E, Person.Contact C, Person.Address A
WHERE E.EmployeeID = C.ContactID
AND E.AddressID = A.AddressID
AND E.EmployeeID=1
FOR XML PATH
Di conseguenza, la query crea due elementi <EmpName
>. Il primo elemento <EmpName
> ha l'elemento figlio <FirstName
> e il secondo elemento <EmpName
> ha gli elementi figlio <MiddleName
> e <LastName
>.
Risultato:
<row EmpID="1">
<EmpName>
<First>Gustavo</First>
</EmpName>
<Address>
<AddrLine1>7726 Driftwood Drive</AddrLine1>
<City>Monroe</City>
</Address>
<EmpName>
<Last>Achong</Last>
</EmpName>
</row>
Colonne con nome specificato come carattere jolly (*)
Se il nome di colonna specificato è un carattere jolly (*), il contenuto della colonna viene inserito come se non fosse stato specificato alcun nome di colonna. Se la colonna non è di tipo -xml, il relativo contenuto viene inserito come nodo di testo, come illustrato nell'esempio seguente:
SELECT EmployeeID "@EmpID",
FirstName "*",
MiddleName "*",
LastName "*"
FROM HumanResources.Employee E, Person.Contact C
WHERE E.EmployeeID = C.ContactID
AND E.EmployeeID=1
FOR XML PATH
Risultato:
<row EmpID="1">GustavoAchong</row>
Se la colonna è di tipo xml, viene inserita la struttura XML corrispondente. Ad esempio, la query seguente specifica "*" come nome della colonna che contiene il codice XML restituito dall'espressione XQuery eseguita sulla colonna Instructions.
SELECT
ProductModelID,
Name,
Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
/MI:root/MI:Location
') as "*"
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH
go
Di seguito è riportato il risultato. Il codice XML restituito dalla XQuery viene inserito senza un elemento di wrapping.
<row>
<ProductModelID>7</ProductModelID>
<Name>HL Touring Frame</Name>
<MI:Location LocationID="10">...</MI:Location>
<MI:Location LocationID="20">...</MI:Location>
...
</row>
Colonne con il nome di un test di nodo XPath
Se il nome della colonna è uno dei test di nodo XPath, il mapping del contenuto viene eseguito come illustrato nella tabella seguente.
Quando il nome della colonna è un test di nodo XPath, il mapping viene eseguito tra il contenuto e il nodo corrispondente. Se il tipo SQL della colonna è xml viene restituito un errore.
Nome colonna | Comportamento |
---|---|
text() |
Per una colonna con nome text(), il valore stringa contenuto nella colonna viene aggiunto come nodo di testo. |
comment() |
Per una colonna con nome comment(), il valore stringa contenuto nella colonna viene aggiunto come commento XML. |
node() |
Per una colonna con nome node(), il risultato è lo stesso di quando il nome della colonna è un carattere jolly (*). |
processing-instruction(name) |
Per una colonna il cui nome corrisponde a quello di un'istruzione di elaborazione, il valore stringa contenuto nella colonna viene aggiunto come valore PI per il nome di destinazione dell'istruzione di elaborazione. |
Nomi di colonna con il percorso specificato come data()
Se il percorso specificato come nome di colonna è "data()", il valore viene gestito come nel codice XML generato come valore atomico. Se anche l'elemento successivo nella serializzazione è un valore atomico, al codice XML viene aggiunto uno spazio. Ciò risulta utile quando si creano valori di elementi e attributi di tipo elenco. La query seguente recupera l'ID del modello di prodotto e l'elenco dei prodotti di quel modello.
SELECT ProductModelID as "@ProductModelID",
Name as "@ProductModelName",
(SELECT ProductID as "data()"
FROM Production.Product
WHERE Production.Product.ProductModelID =
Production.ProductModel.ProductModelID
FOR XML PATH ('')) as "@ProductIDs"
FROM Production.ProductModel
WHERE ProductModelID= 7
FOR XML PATH('ProductModelData')
L'istruzione SELECT nidificata recupera un elenco di ID di prodotti e specifica "data()" come nome di colonna per gli ID di prodotto. Poiché la modalità PATH specifica una stringa vuota per il nome del'elemento riga, non vengono generati elementi riga. I valori vengono invece restituiti come assegnati a un attributo ProductIDs dell'elemento riga <ProductModelData
> dell'istruzione SELECT padre. Risultato:
<ProductModelData ProductModelID="7"
ProductModelName="HL Touring Frame"
ProductIDs="885 887 888 889 890 891 892 893" />
Colonne contenenti un valore NULL per impostazione predefinita
Per impostazione predefinita, la presenza di un valore Null in una colonna viene associato all'assenza dell'attributo, nodo o elemento. Questo funzionamento predefinito può essere sovrascritto richiedendo XML incentrato sugli elementi mediante la direttiva ELEMENTS e specificando XSINIL per richiedere l'aggiunta di elementi per i valori NULL, come illustrato nella query seguente:
SELECT EmployeeID as "@EmpID",
FirstName as "EmpName/First",
MiddleName as "EmpName/Middle",
LastName as "EmpName/Last"
FROM HumanResources.Employee E, Person.Contact C
WHERE E.EmployeeID = C.ContactID
AND E.EmployeeID=1
FOR XML PATH, ELEMENTS XSINIL
Il risultato è illustrato di seguito. Si noti che, non specificando XSINIL, l'elemento <Middle
> non sarà presente.
<row xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" EmpID="1">
<EmpName>
<First>Gustavo</First>
<Middle xsi:nil="true" />
<Last>Achong</Last>
</EmpName>
</row>
Supporto dello spazio dei nomi
In questa versione, il supporto dello spazio dei nomi in modalità PATH è disponibile utilizzando WITH NAMESPACES. Ad esempio, nella query seguente viene illustrata la sintassi WITH NAMESPACES per la dichiarazione di uno spazio dei nomi ("a:") che è possibile utilizzare nell'istruzione SELECT successiva:
WITH XMLNAMESPACES('a' as a)
SELECT 1 as 'a:b'
FOR XML PATH
Esempi
In questi esempi viene illustrato l'utilizzo della modalità PATH nella generazione di codice XML da una query SELECT. Molte di queste query vengono specificate sui documenti XML di istruzioni per la produzione di biciclette archiviati nella colonna Instructions della tabella ProductModel. Per ulteriori informazioni sulle istruzioni XML, vedere Rappresentazione del tipo di dati XML nel database AdventureWorks.
A. Specifica di una query semplice in modalità PATH
La query seguente specifica una modalità FOR XML PATH.
SELECT
ProductModelID,
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH
go
Il risultato seguente è codice XML incentrato sugli elementi in cui il valore di ogni colonna nel set di righe risultante viene inserito in un elemento. Poiché la clausola SELECT non specifica alcun alias per i nomi delle colonne, i nomi degli elementi figlio generati corrispondono ai nomi di colonna corrispondenti nella clausola SELECT. Per ogni riga del set di righe viene aggiunto un tag <row
>.
<row>
<ProductModelID>122</ProductModelID>
<Name>All-Purpose Bike Stand</Name>
</row>
<row>
<ProductModelID>119</ProductModelID>
<Name>Bike Wash</Name>
</row>
Il risultato seguente corrisponde a quello della query in modalità RAW con l'opzione ELEMENTS specificata. Restituisce codice XML incentrato sugli elementi con un elemento <row
> predefinito per ogni riga del set di risultati.
SELECT ProductModelID,
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML RAW, ELEMENTS
È inoltre possibile specificare che il nome dell'elemento riga sovrascriva l'elemento <row
> predefinito. Ad esempio, la query seguente restituisce l'elemento <ProductModel
> per ogni riga del set di risultati.
SELECT ProductModelID,
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModel')
Go
Nel codice XML risultante il nome dell'elemento riga sarà specificato.
<ProductModel>
<ProductModelID>122</ProductModelID>
<Name>All-Purpose Bike Stand</Name>
</ProductModel>
<ProductModel>
<ProductModelID>119</ProductModelID>
<Name>Bike Wash</Name>
</ProductModel>
Se si specifica una stringa di lunghezza zero, l'elemento di wrapping non viene prodotto.
SELECT ProductModelID,
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('')
Go
Risultato:
<ProductModelID>122</ProductModelID>
<Name>All-Purpose Bike Stand</Name>
<ProductModelID>119</ProductModelID>
<Name>Bike Wash</Name>
B. Specifica di nomi di colonna in formato XPath
Nella query seguente il nome di colonna ProductModelID specificato inizia con "@'" e non contiene una barra ("/"). Nel codice XML risultante viene pertanto creato un attributo dell'elemento <row
> con il valore di colonna corrispondente.
SELECT ProductModelID as "@id",
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModelData')
go
Risultato:
< ProductModelData id="122">
<Name>All-Purpose Bike Stand</Name>
</ ProductModelData >
< ProductModelData id="119">
<Name>Bike Wash</Name>
</ ProductModelData >
È possibile aggiungere un singolo elemento di livello principale specificando l'opzione root in FOR XML.
SELECT ProductModelID as "@id",
Name
FROM Production.ProductModel
WHERE ProductModelID=122 or ProductModelID=119
FOR XML PATH ('ProductModelData'), root ('Root')
go
Per generare una gerarchia è possibile includere una sintassi di tipo PATH. Ad esempio, modificando il nome della colonna Name in "SomeChild/ModelName" si otterrà una struttura XML gerarchica, come illustrato nel risultato seguente:
<Root>
<ProductModelData id="122">
<SomeChild>
<ModelName>All-Purpose Bike Stand</ModelName>
</SomeChild>
</ProductModelData>
<ProductModelData id="119">
<SomeChild>
<ModelName>Bike Wash</ModelName>
</SomeChild>
</ProductModelData>
</Root>
Oltre all'ID e al nome del modello di prodotto, la query seguente recupera i percorsi delle relative istruzioni di produzione. Poiché la colonna Instructions è di tipo xml, per il recupero del percorso è specificato il metodo query() del tipo di dati xml.
SELECT ProductModelID as "@id",
Name,
Instructions.query('declare namespace MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions";
/MI:root/MI:Location
') as ManuInstr
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH ('ProductModelData'), root ('Root')
go
Di seguito è riportato il risultato parziale. Poiché la query specifica ManuInstr come nome di colonna, il wrapping del codice XML restituito dal metodo query() viene eseguito in un tag <ManuInstr
> come illustrato di seguito:
<Root>
<ProductModelData id="7">
<Name>HL Touring Frame</Name>
<ManuInstr>
<MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
<MI:step>...</MI:step>...
</MI:Location>
...
</ManuInstr>
</ProductModelData>
</Root>
Nella query FOR XML precedente può essere utile includere gli spazi dei nomi per gli elementi <Root
> e <ProductModelData
>. A questo scopo è necessario innanzitutto definire i prefissi per l'associazione degli spazi dei nomi tramite WITH XMLNAMESPACES,quindi utilizzare tali prefissi nella query FOR XML. Per ulteriori informazioni, vedere Aggiunta di spazi dei nomi tramite WITH XMLNAMESPACES.
WITH XMLNAMESPACES (
'uri1' as ns1,
'uri2' as ns2,
'https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions' as MI)
SELECT ProductModelID as "ns1:ProductModelID",
Name as "ns1:Name",
Instructions.query('
/MI:root/MI:Location
')
FROM Production.ProductModel
WHERE ProductModelID=7
FOR XML PATH ('ns2:ProductInfo'), root('ns1:root')
go
Si noti che il prefisso MI è anche definito in WITH XMLNAMESPACES. Di conseguenza, il metodo query() del tipo xml specificato non definisce il prefisso nel prologo della query. Risultato:
<ns1:root xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions" xmlns="uri2" xmlns:ns2="uri2" xmlns:ns1="uri1">
<ns2:ProductInfo>
<ns1:ProductModelID>7</ns1:ProductModelID>
<ns1:Name>HL Touring Frame</ns1:Name>
<MI:Location xmlns:MI="https://schemas.microsoft.com/sqlserver/2004/07/adventure-works/ProductModelManuInstructions"
LaborHours="2.5" LotSize="100" MachineHours="3" SetupHours="0.5" LocationID="10" >
<MI:step>
Insert <MI:material>aluminum sheet MS-2341</MI:material> into the <MI:tool>T-85A framing tool</MI:tool>.
</MI:step>
...
</MI:Location>
...
</ns2:ProductInfo>
</ns1:root>
C. Generazione di un elenco di valori utilizzando la modalità PATH
La query successiva crea un elenco di valori di ID prodotto per ogni modello di prodotto. Per ogni ID prodotto la query crea inoltre elementi nidificati <ProductName
>, come illustrato in questo frammento XML:
<ProductModelData ProductModelID="7" ProductModelName="..."
ProductIDs="product id list in the product model" >
<ProductName>...</ProductName>
<ProductName>...</ProductName>
...
</ProductModelData>
La query che produce il codice XML desiderato è la seguente:
SELECT ProductModelID as "@ProductModelID",
Name as "@ProductModelName",
(SELECT ProductID as "data()"
FROM Production.Product
WHERE Production.Product.ProductModelID =
Production.ProductModel.ProductModelID
FOR XML PATH ('')) as "@ProductIDs",
(SELECT Name as "ProductName"
FROM Production.Product
WHERE Production.Product.ProductModelID =
Production.ProductModel.ProductModelID
FOR XML PATH ('')) as "ProductNames"
FROM Production.ProductModel
WHERE ProductModelID= 7 or ProductModelID=9
FOR XML PATH('ProductModelData')
Dalla query precedente si noti quanto segue:
- La prima istruzione SELECT nidificata restituisce un elenco di ID prodotto utilizzando il nome di colonna data(). Poiché la query specifica una stringa vuota come nome dell'elemento riga in FOR XML PATH, non vengono generati elementi. L'elenco di valori viene invece assegnato all'attributo ProductID.
- La seconda istruzione SELECT nidificata recupera i nomi prodotto dei prodotti presenti nel modello prodotto. Genera elementi <
ProductName
> che vengono restituiti inseriti nell'elemento <ProductNames
>, poiché la query specifica ProductNames come nome di colonna.
Risultato parziale:
<ProductModelData PId="7"
ProductModelName="HL Touring Frame"
ProductIDs="885 887 ...">
<ProductNames>
<ProductName>HL Touring Frame - Yellow, 60</ProductName>
<ProductName>HL Touring Frame - Yellow, 46</ProductName></ProductNames>
...
</ProductModelData>
<ProductModelData PId="9"
ProductModelName="LL Road Frame"
ProductIDs="722 723 724 ...">
<ProductNames>
<ProductName>LL Road Frame - Black, 58</ProductName>
<ProductName>LL Road Frame - Black, 60</ProductName>
<ProductName>LL Road Frame - Black, 62</ProductName>
...
</ProductNames>
</ProductModelData>
La subquery che crea i nomi di prodotto restituisce il risultato sotto forma di una stringa sostituita con entità e quindi aggiunta al codice XML. Se si aggiunge la direttiva TYPE FOR XML PATH (''), type
, la subquery restituisce il risultato come tipo xml e non viene eseguita la sostituzione con entità.
SELECT ProductModelID as "@ProductModelID",
Name as "@ProductModelName",
(SELECT ProductID as "data()"
FROM Production.Product
WHERE Production.Product.ProductModelID =
Production.ProductModel.ProductModelID
FOR XML PATH ('')
) as "@ProductIDs",
(
SELECT Name as "ProductName"
FROM Production.Product
WHERE Production.Product.ProductModelID =
Production.ProductModel.ProductModelID
FOR XML PATH (''), type
) as "ProductNames"
FROM Production.ProductModel
WHERE ProductModelID= 7 or ProductModelID=9
FOR XML PATH('ProductModelData')
D. Aggiunta degli spazi dei nomi nel codice XML risultante
Come descritto nell'argomento relativo all'aggiunta di spazi dei nomi tramite WITH XMLNAMESPACES, è possibile utilizzare WITH XMLNAMESPACES per includere spazi dei nomi nelle query della modalità PATH. Ad esempio, i nomi specificati nella clausola SELECT includono prefissi degli spazi dei nomi. La query in modalità PATH seguente crea codice XML con spazi dei nomi.
SELECT 'en' as "English/@xml:lang",
'food' as "English",
'ger' as "German/@xml:lang",
'Essen' as "German"
FOR XML PATH ('Translation')
go
L'attributo @xml:lang
aggiunto all'elemento <English
> viene definito nello spazio dei nomi xml predefinito.
Risultato:
<Translation>
<English xml:lang="en">food</English>
<German xml:lang="ger">Essen</German>
</Translation>
La query seguente è simile a quella dell'esempio C, ma utilizza WITH XMLNAMESPACES per includere gli spazi dei nomi nel risultato XML. Per ulteriori informazioni, vedere Aggiunta di spazi dei nomi tramite WITH XMLNAMESPACES.
WITH XMLNAMESPACES ('uri1' as ns1, DEFAULT 'uri2')
SELECT ProductModelID as "@ns1:ProductModelID",
Name as "@ns1:ProductModelName",
(SELECT ProductID as "data()"
FROM Production.Product
WHERE Production.Product.ProductModelID =
Production.ProductModel.ProductModelID
FOR XML PATH ('')
) as "@ns1:ProductIDs",
(
SELECT ProductID as "@ns1:ProductID",
Name as "@ns1:ProductName"
FROM Production.Product
WHERE Production.Product.ProductModelID =
Production.ProductModel.ProductModelID
FOR XML PATH , type
) as "ns1:ProductNames"
FROM Production.ProductModel
WHERE ProductModelID= 7 or ProductModelID=9
FOR XML PATH('ProductModelData'), root('root')
Risultato:
<root xmlns="uri2" xmlns:ns1="uri1">
<ProductModelData ns1:ProductModelID="7" ns1:ProductModelName="HL Touring Frame" ns1:ProductIDs="885 887 888 889 890 891 892 893">
<ns1:ProductNames>
<row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="885" ns1:ProductName="HL Touring Frame - Yellow, 60" />
<row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="887" ns1:ProductName="HL Touring Frame - Yellow, 46" />
...
</ns1:ProductNames>
</ProductModelData>
<ProductModelData ns1:ProductModelID="9" ns1:ProductModelName="LL Road Frame" ns1:ProductIDs="722 723 724 725 726 727 728 729 730 736 737 738">
<ns1:ProductNames>
<row xmlns="uri2" xmlns:ns1="uri1" ns1:ProductID="722" ns1:ProductName="LL Road Frame - Black, 58" />
...
</ns1:ProductNames>
</ProductModelData>
</root>
Vedere anche
Riferimento
Costruzione di codice XML tramite la clausola FOR XML
Concetti
Aggiunta di spazi dei nomi tramite WITH XMLNAMESPACES