SQL Server 使用通用字段元素生成 XML

Posted

技术标签:

【中文标题】SQL Server 使用通用字段元素生成 XML【英文标题】:SQL Server generating XML with generic field elements 【发布时间】:2014-08-20 18:58:51 【问题描述】:

我基本上是在试图扭转这个问题的要求...... SQL Server query xml attribute for an element value

我需要生成一个“行”元素的结果集,其中包含一组“字段”元素,其属性定义了键。

<resultset statement="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
    <field name="id">1</field>
    <field name="version”>0</field>
    <field name="property">My Movie</field>
    <field name="release_date">2012-01-01</field>
    <field name="territory_code”>FR</field>
    <field name="territory_description">FRANCE</field>
    <field name="currency_code”>EUR</field>
</row>
<row>
    <field name="id">2</field>
    <field name="version”>0</field>
    <field name="property">My Sequel</field>
    <field name="release_date">2014-03-01</field>
    <field name="territory_code”>UK</field>
    <field name="territory_description">United Kingdom</field>
    <field name="currency_code”>GBP</field>
</row>
</resultset>

我有一个返回这个的查询...

<resultset statement="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
    <id>1</id>
    <version>0</version>
    <property>My Movie</property>
    <release_date>2012-01-01</release_date>
    <territory_code>FR</territory_code>
    <territory_description>FRANCE</territory_description>
    <currency_code>EUR</currency_code>
</row>
<row>
    <id>2</id>
    <version>0</version>
    <property>My Sequel</property>
    <release_date>2014-03-01</release_date>
    <territory_code>UK</territory_code>
    <territory_description>UNITED KINGDOM</territory_description>
    <currency_code>GBP</currency_code>
</row>
</resultset>

在我的 SQL 语句中使用 FOR XML PATH ('row'), ROOT ('resultset')

我错过了什么?谢谢。

【问题讨论】:

【参考方案1】:

这在 SQL Server 中有点涉及 - 正常行为就是您所看到的 - 列名将用作 XML 元素名。

如果您真的希望所有 XML 元素的名称相同,则必须使用如下代码:

SELECT
    'id' AS 'field/@name',
    id AS 'field',
    '',
    'version' AS 'field/@name',
    version AS 'field',
    '',
    'property' AS 'field/@name',
    property AS 'field',
    '',
    ... and so on ....
FROM Person.Person
FOR XML PATH('row'),ROOT('resultset')

这是确保列名用作&lt;field&gt; 元素上的name 属性所必需的,并且空字符串是必需的,这样SQL XML 解析器就不会混淆哪个name 属性属于什么元素……

【讨论】:

我担心这样的事情会成为答案!不过,它就像一个魅力,感谢您的快速响应。【参考方案2】:

您无需将列指定为常量即可执行此操作,这样您也可以使用select *。它比 marc_s 提供的答案要复杂一些,执行起来会慢很多。

select (
       select T.X.value('local-name(.)', 'nvarchar(128)') as '@name',
              T.X.value('text()[1]', 'nvarchar(max)') as '*'
       from C.X.nodes('/X/*') as T(X)
       for xml path('field'), type
       )
from (
     select (
            select T.*
            for xml path('X'), type
            ) as X
     from dbo.YourTable as T
     ) as C
for xml path('row'), root('resultset')

SQL Fiddle

该查询创建了一个派生表,其中每一行都有一个如下所示的 XML:

<X>
  <ID>1</ID>
  <Col1>1</Col1>
  <Col2>2014-08-21</Col2>
</X>

然后使用 nodes()local-name(.) 将 XML 切碎以创建您想要的形状。

【讨论】:

【参考方案3】:

您的 SELECT 语句需要看起来像这样

SELECT
    'id' AS [field/@name],
    id AS field,
    'version' AS [field/@name],
    version AS field,
    'property' AS [field/@name],
    property AS field,
    'release_date' AS [field/@name],
    release_date AS field,
    'territory_code' AS [field/@name],
    territory_code AS field,
    'territory_description' AS [field/@name],
    territory_description AS field,
    'currency_code' AS [field/@name],
    currency_code AS field

【讨论】:

这将不会按原样工作.....你会得到一个错误:Msg 6852, Level 16, State 1, Line 1 - Attribute-centric column 'field/@name' must not come after a non-attribute-centric sibling in XML hierarchy in FOR XML PATH. 你是对的。我无法针对任何内容运行该语句来验证语法。

以上是关于SQL Server 使用通用字段元素生成 XML的主要内容,如果未能解决你的问题,请参考以下文章