3

我有一个关系,它有一个 XML 列以以下结构存储数据

<Report id="b5d9b8da-7af4-4257-b825-b28af91dd833">
    <CreatedDate>04-12-2012</CreatedDate>
    <LastUpdated>04-12-2012</LastUpdated>
    <Reference>abc123</Reference>
</Report>

我正在编写一个存储过程来检索所有报告并将它们加入并将它们包装在一个名为报告的根节点中。到目前为止,我有以下内容;

WITH XMLNAMESPACES(DEFAULT 'http://www.defaultnamespace.com/1.0')
        SELECT
    @Xml = 
    (

            SELECT
                (
                    SELECT xml.query('.')
                    FROM
                        [database].[Reports]
                    WHERE
                        ClientId = @clientId
                    FOR XML PATH(''),
                    TYPE
                )
            FOR XML PATH('Reports'),
            TYPE
        )

虽然这会以正确的格式返回所有报告,但报告元素上存在一个空白的默认命名空间,如下所示;

<Reports xmlns="http://www.defaultnamespace.com/1.0">
<Report  xmlns="" id="b5d9b8da-7af4-4257-b825-b28af91dd833">
    <CreatedDate>04-12-2012</CreatedDate>
    <LastUpdated>04-12-2012</LastUpdated>
    <Reference>abc123</Reference>
</Report>
</Reports>

有人可以解释在报告元素上排除命名空间的合适方法吗?

非常感谢任何帮助:)

4

2 回答 2

1

它有点混乱,可能效率不高,但您可以使用 XQuery 在中间 XML 上重新定义名称空间。

您可以在 XQuery 中声明默认命名空间,而不是使用 SQL Server WITH XMLNAMESPACES,例如...

if object_id(N'Reports') is not null drop table [Reports];
go
create table [Reports] (
    [ClientId] int not null,
    [xml] [xml] not null
)
go
insert [Reports] ([ClientID], [xml])
    values (1, N'<Report id="b5d9b8da-7af4-4257-b825-b28af91dd833">
    <CreatedDate>04-12-2012</CreatedDate>
    <LastUpdated>04-12-2012</LastUpdated>
    <Reference>abc123</Reference>
</Report>');
go
declare @clientId int = 1
select  (
    select [xml].query('/*:Report')
    from [Reports]
    where ClientId = @clientId
    for xml path('Reports'), type
    ).query('declare default element namespace "http://www.defaultnamespace.com/1.0";
    for $x in /*:Reports return
        <Reports>
        {
            for $y in $x/*:Report return
            <Report>
                {attribute id {$y/@id}}
                {element CreatedDate {$y/*:CreatedDate/text()}}
                {element LastUpdated {$y/*:LastUpdated/text()}}
                {element Reference {$y/*:Reference/text()}}
            </Report>
        }
        </Reports>')
go

这将返回以下 XML 块:

<Reports xmlns="http://www.defaultnamespace.com/1.0">
  <Report id="b5d9b8da-7af4-4257-b825-b28af91dd833">
    <CreatedDate>04-12-2012</CreatedDate>
    <LastUpdated>04-12-2012</LastUpdated>
    <Reference>abc123</Reference>
  </Report>
</Reports>
于 2019-07-10T06:43:25.750 回答
0

您的问题是该列未使用默认命名空间“http://www.defaultnamespace.com/1.0”存储。

所以你的标签的逻辑名称是 NS = "", name =Report。

SQL Server 是绝对正确的。

你想做的就是说

顺便说一句,我存储的那个 XML 数据,我希望你将每个标签从逻辑上附加到每个名称的“”命名空间重写为“http://www.defaultnamespace.com/1.0”中具有相同相对名称的标签" 命名空间,然后将其设为默认命名空间

AFAIK,你不能那样做(但如果你找到办法让我知道!)。您可以获得的最接近的是将其强制转换nvarchar(max)为没有命名空间,然后在应用所需命名空间的情况下再次将其强制转换回来。

于 2012-05-08T10:28:10.850 回答