2012-07-28 13 views
14

tengo el siguiente código XML generado a partir de varias tablas en mi base de datos SQL SERVERConcatenate XML sin la conversión de tipos de cadena

<XMLData> 
... 
<Type>1</Type> 
... 
</XMLData> 

Y

<XMLData> 
... 
<Type>2</Type> 
... 
</XMLData> 

Y

<XMLData> 
... 
<Type>3</Type> 
... 
</XMLData> 

La salida final Necesito es único combinado de la siguiente manera:

<AllMyData> 
    <XMLData> 
     ... 
     <Type>1</Type> 
     ... 
    </XMLData> 
    <XMLData> 
     ... 
     <Type>2</Type> 
     ... 
    </XMLData> 
    <XMLData> 
     ... 
     <Type>3</Type> 
     ... 
    </XMLData> 
<AllMyData> 

NOTA: todos los elementos independientes que estoy combinando tienen el mismo nombre de etiqueta.

Gracias de antemano por consultar esto.

Respuesta

14

tengo el siguiente código XML generado a partir de varias tablas en mi base de datos SQL SERVER

depende de cómo lo tienes, pero si está en una variable XML, puede hacer esto.

declare @XML1 xml 
declare @XML2 xml 
declare @XML3 xml 

set @XML1 = '<XMLData><Type>1</Type></XMLData>' 
set @XML2 = '<XMLData><Type>2</Type></XMLData>' 
set @XML3 = '<XMLData><Type>3</Type></XMLData>' 

select @XML1, @XML2, @XML3 
for xml path('AllMyData') 
5

Si usa for xml type, puede combinar las columnas XML sin emitirlas. Por ejemplo:

select * 
from (
     select (
       select 1 as Type 
       for xml path(''), type 
       ) 
     union all 
     select (
       select 2 as Type 
       for xml path(''), type 
       ) 
     union all 
     select (
       select 3 as Type 
       for xml path(''), type 
       ) 
     ) as Data(XmlData) 
for xml path(''), root('AllMyData'), type 

Esta impresora:

<AllMyData> 
    <XmlData> 
     <Type>1</Type> 
    </XmlData> 
    <XmlData> 
     <Type>2</Type> 
    </XmlData> 
    <XmlData> 
     <Type>3</Type> 
    </XmlData> 
</AllMyData> 
3

Como una adición a la respuesta de Mikael Eriksson - Si tiene un proceso en el que es necesario agregar continuamente nodos y luego querer grupo que bajo un único nodo, esta es una manera de hacerlo:

declare @XML1 XML 
declare @XML2 XML 
declare @XML3 XML 
declare @XMLSummary XML 

set @XML1 = '<XMLData><Type>1</Type></XMLData>' 
set @XMLSummary = (SELECT @XMLSummary, @XML1 FOR XML PATH('')) 

set @XML2 = '<XMLData><Type>2</Type></XMLData>' 
set @XMLSummary = (SELECT @XMLSummary, @XML2 FOR XML PATH('')) 

set @XML3 = '<XMLData><Type>3</Type></XMLData>' 
set @XMLSummary = (SELECT @XMLSummary, @XML3 FOR XML PATH('')) 


SELECT @XMLSummary FOR XML PATH('AllMyData') 
1

Necesitaba hacer lo mismo, pero sin saber cuántas filas/variables estaban involucradas y sin agregar un esquema adicional, así que esta era mi solución. Siguiendo este patrón, puedo generar tantos fragmentos como quiera, combinarlos, pasarlos entre PROCS o incluso devolverlos desde procs y en cualquier punto, envolverlos en contenedores sin modificar los datos o forzarlos a agregar estructura XML en mis datos. Utilizo este enfoque con puntos finales HTTP para proporcionar servicios web XML y con otro truco que convierte XML en JSON para proporcionar servicios web JSON.

-- SETUP A type (or use this design for a Table Variable) to temporarily store snippets into. The pattern can be repeated to pass/store snippets to build 
    -- larger elements and those can be further combined following the pattern. 
    CREATE TYPE [dbo].[XMLRes] AS TABLE(
     [xmlResult] [xml] NULL 
    ) 
    GO 


    -- Call the following as much as you like to build up all the elements you want included in the larger element 
    INSERT INTO @XMLRes (xmlResult) 
     SELECT 
      ( 
       SELECT 
        'foo' '@bar' 
       FOR XML 
        PATH('SomeTopLevelElement') 
      ) 

    -- This is the key to "concatenating" many snippets into a larger element. At the end of this, add " ,ROOT('DocumentRoot') " to wrapp them up in another element even 
    -- The outer select is a time from user2503764 that controls the output column name 

    SELECT (
    SELECT XmlData as [*] 
    FROM 
     (
     SELECT 
      xmlResult AS [*] 
     FROM 
      @XmlRes 
     WHERE 
      xmlResult IS NOT NULL 
     FOR XML PATH(''), TYPE 
     ) as DATA(XmlData) 
    FOR XML PATH('') 
    ) as [someColumnName] 
6

que no puedo comentar, pero puedo responder por lo que a pesar de que creo que es un comentario más apropiado, Voy a ampliar en lo rainabba contestado arriba para añadir un poco más de control. Mi código .Net necesita saber el nombre de la columna devuelto, por lo que no puedo confiar en los nombres autogenerados, pero si no necesito el tip rainabba proporcionado anteriormente.

De esta forma, el xml se puede concatenar efectivamente en una sola fila y la columna resultante se llama. Puede usar este mismo enfoque para asignar los resultados a una variable XML y devolverlos desde un PROC también.

SELECT (
SELECT XmlData as [*] 
FROM 
    (
    SELECT 
     xmlResult AS [*] 
    FROM 
     @XmlRes 
    WHERE 
     xmlResult IS NOT NULL 
    FOR XML PATH(''), TYPE 
    ) as DATA(XmlData) 
FOR XML PATH('') 
) as [someColumnName] 
+0

agradable además. Gracias. Es probable que no pueda hacer ningún comentario porque todavía no tiene suficientes representantes. Uno de los catch-22 de StackOverflow y sitios similares. – rainabba

+0

Gracias! Puedo comentar aquí ahora (porque es mi respuesta?) – user2503764

0

PROCEDIMIENTO alter usp_fillHDDT @code int

COMO COMENZAR

DECLARE XML @HD, @ DT XML;

SET NOCOUNT ON; 
select invhdcode, invInvoiceNO,invDate,invCusCode,InvAmount into #HD 
from dbo.trnInvoiceHD where [email protected] 

select invdtSlNo No,invdtitemcode ItemCode,invdtitemcode ItemName, 
invDtRate Rate,invDtQty Qty,invDtAmount Amount ,'Kg' Unit into #DT from 
dbo.trnInvoiceDt where [email protected] 

set @HD = (select * from #HD HD FOR XML AUTO,ELEMENTS XSINIL); 
set @DT = (select* from #DT DT FOR XML AUTO,ELEMENTS XSINIL); 

SELECT CAST ('<OUTPUT>'+ CAST (ISNULL(@HD,'') AS VARCHAR(MAX))+ CAST (ISNULL(@DT,'') AS VARCHAR(MAX))+ '</OUTPUT>' AS XML) 

FIN

-1
public String ReplaceSpecialChar(String inStr) 
{ 
    inStr = inStr.Replace("&", "&amp;"); 
    inStr = inStr.Replace("<", "&lt;"); 
    inStr = inStr.Replace(">", "&gt;"); 
    inStr = inStr.Replace("'", "&#39;"); 
    inStr = inStr.Replace("\"", "&quot;"); 
    return inStr; 
}