2

SQL スクリプトを介して生成したい XML ドキュメントが与えられましたが、このようなことをしたことがなく、必要な最終的な XML を生成できるようにするための例を見つけることができませんでした (そして、私が必要とするものにより適している場合、利用可能な方法のどれが利用可能かわかりません-EXPLICITまたはPATH、またはそれが可能な場合でも)。SQL から XML を生成した経験のある人が正しい方向に向けてくれることを願っています (または、私がやろうとしていることは不可能であり、サブクエリでそれを行う必要があることを教えてください)。

シナリオは、単一のテーブルから製品の詳細を返すことです (必要な値ごとにサブクエリを実行する必要はありません)。

生成できることを望んでいるxmlは次のようになります(この形式を制御することはできません):

<records>
    <record>
        <fields>
            <field name="id">
                <values>
                    <value>666111</value>
                </values>
            </field>
            <field name="name">
                <values>
                    <value>
                        <![CDATA[My Product Title]]>
                    </value>
                </values>
            </field>
        </fields>
    </record>
    <record>
        ...
    </record>
</records>

私が見た最初の方法は、 FOR XML PATH を使用することです

SELECT TOP 2 
    'id' AS "@name",
    p.product_id as [value], 
    p.title
FROM products p 
ORDER BY p.product_id DESC
FOR XML PATH ('field'), ROOT ('fields'), ELEMENTS;

これにより、次の XML が得られます。

<fields>
  <field name="id">
    <value>20624</value>
    <title>test154</title>
  </field>
  <field name="id">
    <value>20623</value>
    <title>test153</title>
  </field>
</fields>

これにより、必要な '' が得られますが、次の要素に必要なレイアウトを指定することはできません。

FOR XML EXPLICIT も調べました

SELECT TOP 2
    1 AS Tag, NULL AS Parent,
    p.product_id AS [record!1!product_id!ELEMENT],
    NULL AS [values!2!value!ELEMENT]
FROM products p 
UNION ALL
SELECT TOP 2 
    2, 1,
    p.product_id,
    p.title
FROM products p 
ORDER BY [record!1!product_id!ELEMENT] DESC
FOR XML EXPLICIT;

これにより、次の XML が得られました。

<record>
  <product_id>20624</product_id>
  <values>
    <value>test154</value>
  </values>
</record>
<record>
  <product_id>20623</product_id>
  <values>
    <value>test153</value>
  </values>
</record>

リクエストを作成したり、正しい線に沿ったものを取得したりできることに少し迷っています(そして、1回のルックアップでやりすぎていると思います。それが私の問題の原因です)。たとえそれが良いガイドを指し示していたとしても (私が見つけた唯一のものは例に関しては非常に貧弱でした - それらはあなたがそれらを構築/変更する方法の微妙な点を示していません)

4

3 に答える 3

2

これはあなたが探しているかもしれないクエリです

真ん中にあるの,''は、同じ名前の複数の要素を上下に作成できるトリックです...

DECLARE @tbl TABLE(id INT,name VARCHAR(100));
INSERT INTO @tbl VALUES
 (666111,'My Product Title 111')
,(666222,'My Product Title 222');

SELECT 
(
    SELECT  'id' AS [field/@name]
           ,id AS [field/values/value]
           ,''
           ,'name' AS [field/@name]
           ,name AS [field/values/value]
    FOR XML PATH('fields'),TYPE
)
FROM @tbl AS tbl
FOR XML PATH('record'),ROOT('records')

結果

<records>
  <record>
    <fields>
      <field name="id">
        <values>
          <value>666111</value>
        </values>
      </field>
      <field name="name">
        <values>
          <value>My Product Title 111</value>
        </values>
      </field>
    </fields>
  </record>
  <record>
    <fields>
      <field name="id">
        <values>
          <value>666222</value>
        </values>
      </field>
      <field name="name">
        <values>
          <value>My Product Title 222</value>
        </values>
      </field>
    </fields>
  </record>
</records>

更新:私の知る限り、セクションを追加するきれいな方法はありませCDATA

いくつかの理由により、Microsoft の人々は、CDATA セクションは不要であると考えています。そうではありませんが、それでも時々要求されます...

セクションを追加する唯一のクリーンな方法は、 を使用することでした。別の回避策は、次のようなものを配置することでした (実際のデータでは決して発生しない 2 つの文字を使用してください。CDATAFOR XML EXPLICIT'|' + name + '#'

次に、結果を にキャストしNVARCHAR(MAX)、これらの文字を文字列ベースで置き換えることができます。

これにより、XMLが文字列として返されます

SELECT 
REPLACE(REPLACE(CAST(
(
SELECT 
(
    SELECT  'id' AS [field/@name]
           ,id AS [field/values/value]
           ,''
           ,'name' AS [field/@name]
           ,'|' + name + '#' AS [field/values/value]
    FOR XML PATH('fields'),TYPE
)
FROM @tbl AS tbl
FOR XML PATH('record'),ROOT('records')
) AS NVARCHAR(MAX)),'|','<![CDATA['),'#',']]>')

現時点では、これをXMLCDATA にキャストし直すことはできません :-(

于 2016-07-06T14:01:58.103 に答える
1

私が使用した最終的なSQLは次のとおりです。

SELECT TOP 2
(
    SELECT  
        (SELECT 'id' AS [field/@id],
        product_id [field/values/value]
        FOR XML PATH(''), TYPE),
        (SELECT 'title' AS [field/@id],
        title [field/values/value]
        FOR XML PATH(''), TYPE)
    FOR XML PATH('fields'), TYPE
)
FROM products 
FOR XML PATH('record'), ROOT('records')

これにより、出力を少し簡単に操作できるようになります。

@xdd と特に @Shnugo の両方に感謝します。最終的な解決策は@Shnugoの提案に基づいており、余分な空白行を入れるというトリックを回避しています.

于 2016-07-06T15:21:55.143 に答える
1

そんな感じ

    declare @t table (id varchar(10))

    insert into @t values ('1')
    insert into @t values ('2')

    select (
            select 
                    t.id 'fields/field/@id'
                    , t.id 'fields/field/name'
                from @t t
                for xml path(''), type
        ) 'records/record'
        for xml path('')
于 2016-07-06T14:10:21.523 に答える