Pregunta

Estoy tratando de generar algo de XML con varios niveles de anidación, y corriendo el riesgo de simplificar en exceso, el XML de salida será ligeramente del formato:

<invoice number="1">
 <charge code="foo" rate="123.00">
  <surcharge amount="10%" />
 </charge>
 <charge code="bar" />
</invoice>

El esquema de base He heredado para este pasa a tener cargas almacenadas en tablas diferentes, lo que significa que los recargos se almacenan de forma diferente, según la tabla de donde la carga era.

UNIONs con FOR XML , he hecho algunos UNIONing en un CTE, por lo que algo a lo largo del líneas de:

WITH Charges ( [@code], [@rate], surcharge, InvoiceId ) AS (
    SELECT code AS [@Code], amount AS [@rate], NULL as surcharge, InvoiceId
    FROM item.charges
UNION ALL
    SELECT 
        code AS [@Code], 
        amount AS [@rate],
        (
             SELECT amount AS [@amount]
             FROM order.surcharges os
             WHERE oc.ChargeId = os.ChargeId
             FOR XML PATH('surcharge'), TYPE
        ), 
        InvoiceId
    FROM order.charges oc
)
SELECT
    Number AS [@number],
    (
         SELECT
             [@code],
             [@rate],
             surcharge
         FROM Charges
         WHERE Charges.InvoiceId = i.InvoiceId
    )
FROM Invoices i
FOR XML PATH( 'invoice' ), TYPE

Ahora, que es muy cerrar, dando (Nota del <surcharge> anidada):

<invoice number="1">
 <charge code="foo" rate="123.00">
  <surcharge>
   <surcharge amount="10%" />
  </surcharge>
 </charge>
 <charge code="bar" />
</invoice>

Pero tengo que encontrar una manera de conseguir la consulta final para incluir el valor de una columna XML a ser tratado como el contenido del elemento, en lugar de como un nuevo elemento. Es esto posible, o tengo que tomar un nuevo enfoque?

¿Fue útil?

Solución 2

Parece que el nombramiento de la columna (falso) como "*" utilizará que el contenido de esa columna que el contenido del elemento, por lo que cambiar el SQL de la siguiente manera hace que funcione:

WITH Charges ( [@code], [@rate], surcharge, InvoiceId ) AS (
    SELECT code AS [@Code], amount AS [@rate], NULL as surcharge, InvoiceId
    FROM item.charges
UNION ALL
    SELECT 
        code AS [@Code], 
        amount AS [@rate],
        (
             SELECT amount AS [@amount]
             FROM order.surcharges os
             WHERE oc.ChargeId = os.ChargeId
             FOR XML PATH('surcharge'), TYPE
        ), 
        InvoiceId
    FROM order.charges oc
)
SELECT
    Number AS [@number],
    (
         SELECT
             [@code],
             [@rate],
             surcharge AS [*] -- Thsi will embed the contents of the previously generated XML in here.
         FROM Charges
         WHERE Charges.InvoiceId = i.InvoiceId
    )
FROM Invoices i
FOR XML PATH( 'invoice' ), TYPE

Otros consejos

Tiene una consulta que devuelve la columna filas haya numerosas Yo esperaría que la consulta que publicas para dar el error (@charge, @rate, y un tipo XML.):

Sólo una expresión se puede especificar en la lista de selección cuando la subconsulta No se introduce con EXISTS.

Sin embargo, eso es fácil de solucionar moviendo la consulta a un outer apply. Para quitar el elemento de doble surcharge, se podía mover los nombres de las columnas XML en cuanto al fondo como sea posible, como:

;WITH Charges (code, rate, surcharge, InvoiceId) AS 
    (
    SELECT  code, amount, NULL, InvoiceId
    FROM    @charges
    UNION ALL
    SELECT  code
    ,       amount
    ,       (
            SELECT  amount AS [@amount]
            FROM    @surcharges os
            WHERE   oc.ChargeId = os.ChargeId
            FOR XML PATH('surcharge'), TYPE
            )
    ,       InvoiceId
    FROM    @charges oc
)
SELECT  Number AS [@number]
,       c.code as [charge/@code]
,       c.rate as [charge/@rate]
,       c.surcharge as [charge]
FROM    @Invoices i
outer apply
        (
        SELECT  code
        ,       rate
        ,       surcharge
        FROM    Charges
        WHERE   Charges.InvoiceId = i.InvoiceId
        ) c
WHERE   i.InvoiceID = 1
FOR XML PATH( 'invoice' ), TYPE

Esto imprimir, por ejemplo:

<invoice number="1">
  <charge code="1" rate="1" />
</invoice>
<invoice number="1">
  <charge code="1" rate="1">
    <surcharge amount="1" />
  </charge>
</invoice>

El primer elemento proviene de la parte superior de la unión, donde surcharge = null.

creo que se puede hacer esto mediante la omisión del tipo nodo raíz en su "camino para XML ( 'suplemento')" comunicado. Es decir, el uso "para la ruta XML ( '')" en su lugar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top