2012-12-16 18 views
6

Sto utilizzando SQL Server 2008 e voglio recuperare elementi XML e restituire l'elemento stesso e i relativi attributi senza elementi secondari e senza text(). Ad esempio, il seguente codice XML ha 4 nodi (doc, mela, b, banane):Recupero di un elemento senza elementi secondari in SQL Server

<doc> 
<apple type="bramley"> tasty <b>yum!</b> </apple> 
<banana color="yellow" shape="bendy"> nice in smoothies </banana> 
</doc> 

Vorrei ritorno:

<doc/> 
<apple type="bramley"/> 
<b/> 
<banana color="yellow" shape="bendy"/> 

Eg doc deve essere restituito senza alcun sub-nodi e mela deve essere restituito senza il sottonodo b. Ma il problema è che se utilizzo i nodi di SQL Server e il metodo di query non riesco a rimuovere i nodi secondari. Utilizzo di SQL Server 2008 la più vicina che ho è:

declare @x xml = '<doc> 
    <apple type="bramley"> tasty <b>yum!</b> </apple> 
    <banana color="yellow" shape="bendy"> nice in smoothies </banana> 
</doc>'; 

select 
    c.query('local-name(.)') as Node, 
    c.query('for $e in . return <xx> {$e/@*} </xx>') as Attr 
from @x.nodes('//*') as T(c); 

questo diventa il nome di ciascun nodo (usando local-nome) e gli attributi del nodo e ritorni:

Node Attr 
---- ---- 
doc  <xx /> 
apple <xx type="bramley" /> 
b  <xx /> 
banana <xx color="yellow" shape="bendy" /> 

mi rendo conto che posso elaborare questo risultato, convertire Attr in varchar, sostituire xx con la colonna Node e riconvertire in XML. Ma c'è un modo più semplice senza la manipolazione delle stringhe?

PS: Se serve, non mi importa se la soluzione utilizza SQL Server 2008 o SQL Server 2012.

risposta

1

Di solito si usa la costruzione elemento con i nomi dei tag dinamici, ma SQL Server non supporta questa :

declare @x xml = '<doc> 
    <apple type="bramley"> tasty <b>yum!</b> </apple> 
    <banana color="yellow" shape="bendy"> nice in smoothies </banana> 
</doc>'; 

select 
    c.query('local-name(.)') as Node, 
    c.query('for $e in . return element { local-name($e) } { $e/@* } </xx>') as Attr 
from @x.nodes('//*') as T(c); 

In qualità di XQuery aggiornamento alternativi (testato con SQL Server 2012), siamo in grado di recuperare tutti i nodi (con tutti i contenuti) e cancellare i loro subnotes.

DECLARE @x xml = '<doc>test 
    <apple type="bramley"> tasty <b>yum!</b> </apple> 
    <banana color="yellow" shape="bendy"> nice in smoothies </banana> 
</doc>'; 

-- Fetch all nodes 
SET @x = @x.query('//*') 
-- Delete all subnodes 
SET @x.modify('delete /*/node()') 

select 
    c.query('.') as NewNode 
from @x.nodes('/*') as T(c); 
+0

Grazie! Lo proverò più tardi oggi – Ubercoder

+0

OK L'ho provato in SQL Server ma non mi piace - l'errore è _Sono supportate solo espressioni costanti per l'espressione name dell'elemento calcolato e dei costruttori degli attributi_. Quindi penso che ** local-name ($ e) ** non sia consentito come costruttore di elementi nel server SQL (ciò rende il costruttore di elementi non molto utile in SQL Server ma questa è un'altra storia). Ci sono altre varianti di XQuery che posso testare? – Ubercoder

+0

Sembra essere un vero problema. [C'è una risposta a un'altra domanda] (http://stackoverflow.com/a/4418821/695343) che utilizza la concatenazione di stringhe per costruire l'XML - sembra davvero, davvero brutto. "Se questo approccio è offensivo, puoi smettere di leggere ora :)" ... Meglio dare un'occhiata al tuo problema da un più alto livello di vista; qual è il tuo problema reale che stai cercando di risolvere? –

Problemi correlati