【问题标题】:XML - add a namespace not in rootXML - 添加不在根目录中的命名空间
【发布时间】:2020-09-16 21:21:48
【问题描述】:

我需要在具有这种格式的 SQL Server 中构建 XML。您可以看到第一行有两个 XMLNAMESPACES,但在 Location 旁边还有第三个。

<arrayofstuff xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypes">
  <stuff>
    <Description>blue</Description>
    <Location xmlns:d3p1="http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues">
      <d3p1:Code>64</d3p1:Code>
      <d3p1:Description>Balloons</d3p1:Description>
    </Location>
  </stuff>
</arrayofstuff>

这是我目前所拥有的,以及一些示例数据。看起来第一个查询中有一个嵌套的 XML 查询,但我似乎无法第二次使用 WITH 语句,因为它必须是批处理中的第一个命令,所以我不知道该怎么做.

IF EXISTS(SELECT 1 FROM sys.tables WHERE object_id = OBJECT_ID('myTable'))
BEGIN;
    DROP TABLE [myTable];
END;
GO

CREATE TABLE [myTable] (
    [myTableID] INTEGER NOT NULL IDENTITY(1, 1),
    [Description] VARCHAR(MAX) NULL,
    [sourceID] INTEGER NOT NULL ,
    [Location] VARCHAR(255) NULL,
    [Code] VARCHAR(255) NULL,
    [Location_Desc] VARCHAR(255) NULL,
    PRIMARY KEY ([myTableID])
);
GO

INSERT INTO myTable([SourceID],[Description],[Location],[Code],[Location_Desc])
VALUES(3,'yellow','Oxford County','64','list'),
(3,'blue','Fraser Lake','64','list'),
(2,'red','San Marcello Pistoiese','64','list'),
(2,'green','Gembloux','64','list'),
(2,'green','Yeongcheon','64','list')

GO

WITH XMLNAMESPACES (default 'http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypess', 'http://www.w3.org/2001/XMLSchema-instance' as i )
SELECT 
[sourceID]
,cast(stuff((
 SELECT
[Description] as [Description]
,[Code] AS [Location/Code]
,[Location_Desc] AS [Location/Description]
FROM [myTable] mnbm
where mnbm.[sourceID] = p.[sourceID]
for xml path('stuff'), root ('arrayofstuff')
),1,0,'') as xml) as Ids
from [myTable]  p
group by 
p.[sourceID]

这是我目前输出的结果:

<arrayofstuff xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypess">
  <stuff>
    <Description>commodo</Description>
    <Location>San Marcello Pistoiese</Location>
  </stuff>
  <stuff>
    <Description>ipsum</Description>
    <Location>Gembloux</Location>
  </stuff>
  <stuff>
    <Description>ipsum</Description>
    <Location>Yeongcheon</Location>
  </stuff>
</arrayofstuff>

【问题讨论】:

    标签: sql-server xml tsql xquery


    【解决方案1】:

    xmlns:d3p1="http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues" 必须出现在 Location 元素上是否有某些特定原因?命名空间可以在 XML 文档中的任何位置定义,只要它们在被引用之前就已经定义好了,因此您可以在根元素上将其定义为 WITH XMLNAMESPACES 的一部分,例如:

    drop table if exists dbo.myTable;
    
    create table dbo.myTable (
        myTableID integer not null identity(1, 1),
        [Description] varchar(max) null,
        sourceID integer not null,
        [Location] varchar(255) null,
        Code varchar(255) null,
        Location_Desc varchar(255) null,
        primary key (myTableID)
    );
    
    insert into dbo.myTable (sourceID,[Description],[Location],Code,Location_Desc)
    values (1, 'blue', 'Somewhere', '64', 'Balloons');
    
    with xmlnamespaces (
        default 'http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypess',
        'http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues' as d3p1,
        'http://www.w3.org/2001/XMLSchema-instance' as i )
    select
        [sourceID],
        cast((
            select
                [Description],
                Code as [Location/d3p1:Code],
                Location_Desc as [Location/d3p1:Description]
            from dbo.myTable mnbm
            where mnbm.sourceID = p.sourceID
            for xml path('stuff'), root('arrayofstuff')
        ) as xml) as Ids
    from dbo.myTable p
    group by p.sourceID;
    

    产量:

    <arrayofstuff
      xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:d3p1="http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues"
      xmlns="http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypess">
      <stuff>
        <Description>blue</Description>
        <Location>
          <d3p1:Code>64</d3p1:Code>
          <d3p1:Description>Balloons</d3p1:Description>
        </Location>
      </stuff>
    </arrayofstuff>
    

    【讨论】:

    • 在 location 标记中定义命名空间的原因很简单,这就是我正在使用的应用程序所做的,所以我认为我需要这样做。我会测试你的建议,如果这就是它所需要的,那就太好了。
    • 应用程序确实采用了建议的方式。
    【解决方案2】:

    您可以尝试以下基于 XQuery 和 FLWOR 表达式的解决方案。

    它正在生成与所需输出完全一致的 XML。

    这是一个两步过程:

    1. 编写原始 XML。
    2. 根据所需的输出使用命名空间塑造原始 XML。

    SQL

    -- DDL and sample data population, start
    DECLARE @myTable TABLE
    (
        [myTableID] INTEGER NOT NULL IDENTITY(1, 1),
        [Description] VARCHAR(MAX) NULL,
        [sourceID] INTEGER NOT NULL,
        [Location] VARCHAR(255) NULL,
        [Code] VARCHAR(255) NULL,
        [Location_Desc] VARCHAR(255) NULL,
        PRIMARY KEY ([myTableID])
    );
    
    INSERT INTO @myTable
    (
        [sourceID],
        [Description],
        [Location],
        [Code],
        [Location_Desc]
    )
    VALUES
    (3, 'yellow', 'Oxford County', '64', 'list'),
    (3, 'blue', 'Fraser Lake', '64', 'list'),
    (2, 'red', 'San Marcello Pistoiese', '64', 'list'),
    (2, 'green', 'Gembloux', '64', 'list'),
    (2, 'green', 'Yeongcheon', '64', 'list');
    -- DDL and sample data population, end
    
    ;WITH rs AS
    (
        SELECT [sourceID]
            , (SELECT [Description] AS [Description]
                , [Code] AS [Code]
                , [Location_Desc] AS [Location_Desc]
                FROM @myTable AS mnbm
                WHERE mnbm.[sourceID] = p.[sourceID]
                FOR XML PATH('stuff'), TYPE, ROOT('arrayofstuff')
            ) AS Ids
        FROM @myTable AS p
        GROUP BY p.[sourceID]
    )
    SELECT rs.sourceID, rs.Ids AS [Before]
        , rs.Ids.query('<arrayofstuff xmlns:i="http://www.w3.org/2001/XMLSchema-instance" 
        xmlns="http://schemas.datacontract.org/2004/07/ACME.Domain.Core.ComplexTypes">
    {
        for $x in /*:arrayofstuff/*:stuff
        return <stuff>
            <Description>{data($x/*:Description)}</Description>
            <Location xmlns:d3p1="http://schemas.datacontract.org/2004/07/ACME.Infrastructure.CodeValues">
                <d3p1:Code>{data($x/*:Code)}</d3p1:Code>
                <d3p1:Description>{data($x/*:Location_Desc)}</d3p1:Description>
            </Location>
        </stuff>
    }
    </arrayofstuff>') AS [After]
    FROM rs;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 1970-01-01
      • 1970-01-01
      • 2016-07-08
      • 2012-02-21
      • 1970-01-01
      • 2011-09-16
      相关资源
      最近更新 更多