【问题标题】:Converting attribute-based xml to json in SQL Server在 SQL Server 中将基于属性的 xml 转换为 json
【发布时间】:2017-10-04 15:03:29
【问题描述】:

我正在使用来自https://www.red-gate.com/simple-talk/sql/t-sql-programming/producing-json-documents-from-sql-server-queries-via-tsql/ 的例程将存储在表中 XML 列中的 XML 转换为 json(通过 ajax 提供服务)

IF OBJECT_ID (N'dbo.FlattenedJSON') IS NOT NULL
   DROP FUNCTION dbo.FlattenedJSON
GO

CREATE FUNCTION dbo.FlattenedJSON (@XMLResult XML)
RETURNS NVARCHAR(MAX)
WITH EXECUTE AS CALLER
AS
BEGIN
    DECLARE @JSONVersion NVARCHAR(MAX), @Rowcount INT

    SELECT @JSONVersion = '', @rowcount=COUNT(*) 
    FROM @XMLResult.nodes('/root/*') x(a)

    SELECT @JSONVersion = @JSONVersion +
           STUFF((SELECT TheLine 
                  FROM 
                      (SELECT ',
    {'+
      STUFF((SELECT ',"'+COALESCE(b.c.value('local-name(.)','NVARCHAR(255)'),'')+'":"'+
       REPLACE( --escape tab properly within a value
         REPLACE( --escape return properly
           REPLACE( --linefeed must be escaped
             REPLACE( --backslash too
               REPLACE(COALESCE(b.c.value('text()[1]','NVARCHAR(MAX)'),''),--forwardslash
               '\', '\\'),   
              '/', '\/'),   
          CHAR(10),'\n'),   
         CHAR(13),'\r'),   
       CHAR(09),'\t')   
     +'"'   
     FROM x.a.nodes('*') b(c) 
     FOR XML PATH(''),TYPE).value('(./text())
[1]','NVARCHAR(MAX)'),1,1,'')+'}'
   FROM @XMLResult.nodes('/root/*') x(a)
   ) JSON(theLine)
  FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)' )
,1,1,'')
IF @Rowcount>1 RETURN '['+@JSONVersion+']'
RETURN @JSONVersion

当 XML 是时它工作得很好

<product>
...
    <height>123</height>
    <width>234</width>
</product>

返回这个结果:

{..."height":"123","width","234"}

但另一个供应商以这种格式提供数据

<product>
    <int name="height">123</int>
    <int name="width">234</int>
    <str name="colour">red</str>
 ...
 </product>

返回这个结果:

{"int":"123","int":"234","str":"red"}

这没什么用。可以为这种格式的 XML 制作类似于上面的例程吗?

有些属性是数组

<arr name="images">
    <str>image1.jpg</str>
    <str>image2.jpg</str>
    <str>image3.jpg</str>
</arr>

但我可以没有这些。

【问题讨论】:

  • 如果将第 17 行替换为 STUFF((SELECT ',"'+COALESCE(b.c.value(@name,'NVARCHAR(255)'),'') +'":"'+ etc ... 使用 name 属性?这应该为第二种形式的文档产生所需的输出。仍然不适用于数组版本
  • 可能遗漏了一些简单的东西,但我收到了这个错误:必须声明@name。如果我把它放在单引号中,它会编译,但返回 null。
  • 您是否考虑过在 SQL 上编写 C# clr 来生成 json?
  • 不,如果sql中的一个函数可以做一个转换,那么另一个也应该可以。

标签: sql-server json xml xpath xquery


【解决方案1】:

不知道,如果这仍然是一个悬而未决的问题,但我想提供FLOWR-queries 以帮助您:

整个方法是完全可内联的,可以作为单个调用放置在函数中。

在此表中,每种格式都有一个示例:

DECLARE @tbl TABLE (ID INT IDENTITY, YourXml XML);
INSERT INTO @tbl VALUES
(N'<product>
    <colour>red</colour>
    <height>123</height>
    <width>234</width>
</product>')
,(N'<product>
    <int name="height">123</int>
    <int name="width">234</int>
    <str name="colour">red</str>
</product>');

--CTE transformed 将使用 FLOWR 查询来转换 XML,以便两者看起来相同:一个节点看起来像这样:&lt;nd name="colour" type="unknown"&gt;red&lt;/nd&gt;

WITH transformed AS
(
    SELECT ID,
    YourXml.query
    (N'
        <product>
        {
        for $nd in /product/*
        return 
        if (empty($nd/@name)) then
            <nd name="{local-name($nd)}" type="unknown">{$nd/text()}</nd>
        else
            <nd name="{$nd/@name}" type="{local-name($nd)}">{$nd/text()}</nd>
        }
        </product>  
    ') AS newXml
    FROM @tbl
)

--select 将返回 json

SELECT t1.ID, N'{"' + 
               STUFF(
               (
                SELECT N'","' 
                      + nd.value(N'@name',N'nvarchar(max)')
                      + N'":"'  
                      + nd.value(N'text()[1]',N'nvarchar(max)')
                FROM transformed AS t2 
                CROSS APPLY  t2.newXml.nodes(N'/product/nd') AS A(nd)
                WHERE t1.ID=t2.ID
                FOR XML PATH('')),1,3,'') + N'"}'
FROM transformed AS t1
GROUP BY ID

结果:

ID  JSON
1   {"colour":"red","height":"123","width":"234"}
2   {"height":"123","width":"234","colour":"red"}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-26
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    • 2019-01-04
    相关资源
    最近更新 更多