You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL Server XML列解析失败求助:含defaultfontfamily命名空间

解决SQL Server XML列解析问题(针对Reporting Services报表定义)

在SQL Server的Catalog表中处理报表XML时,部分行无法正常解析。排查发现这些异常行的XML使用了http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition/defaultfontfamily命名空间,且包含额外的<df:DefaultFontFamily>节点,添加该命名空间后问题仍未解决。

正常行XML示例

<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">
  <AutoRefresh>0</AutoRefresh>
  <DataSources>

异常行XML示例

<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns:df="http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition/defaultfontfamily" MustUnderstand="df">
  <df:DefaultFontFamily>Segoe UI</df:DefaultFontFamily>
  <AutoRefresh>0</AutoRefresh>
  <DataSources>

用户原SQL代码

WITH XMLNAMESPACES 
( DEFAULT 
  'http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition'
, 'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' AS ReportDefinition
, 'http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition/defaultfontfamily' AS df)
SELECT  
CATDATA.Name AS ReportName
,CATDATA.Path AS ReportPathLocation
,xmlcolumn.value('(@Name)[1]', 'VARCHAR(250)') AS DataSetName  
,xmlcolumn.value('(Query/DataSourceName)[1]','VARCHAR(250)') AS DataSourceName 
,xmlcolumn.value('(Query/CommandText)[1]','VARCHAR(2500)') AS CommandText
,reportXML
FROM (  
    SELECT C.Name
    ,c.Path
    ,CONVERT(XML,CONVERT(VARBINARY(MAX),C.Content)) AS reportXML
    FROM  ReportServer.dbo.Catalog C
    WHERE  C.Content is not null
    AND  C.Type = 2
    ) CATDATA 
outer APPLY reportXML.nodes('/Report/DataSets/DataSet') xmltable ( xmlcolumn )
--WHERE xmlcolumn.value('(Query/CommandText)[1]','VARCHAR(250)') LIKE '%2_%'
ORDER BY CATDATA.Name

问题原因与解决方案

问题核心是默认命名空间不匹配:异常行使用2016版报表定义命名空间http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition,而原代码仅默认指定2010版命名空间,导致2016版XML节点无法被识别。

方案1:显式兼容两个版本命名空间

适合需要区分报表版本的场景,兼容性更强:

WITH XMLNAMESPACES 
( 
    'http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition' AS ns2010,
    'http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition' AS ns2016,
    'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' AS rd,
    'http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition/defaultfontfamily' AS df
)
SELECT  
    CATDATA.Name AS ReportName,
    CATDATA.Path AS ReportPathLocation,
    COALESCE(
        xmlcolumn2010.value('(@Name)[1]', 'VARCHAR(250)'),
        xmlcolumn2016.value('(@Name)[1]', 'VARCHAR(250)')
    ) AS DataSetName,
    COALESCE(
        xmlcolumn2010.value('(ns2010:Query/ns2010:DataSourceName)[1]','VARCHAR(250)'),
        xmlcolumn2016.value('(ns2016:Query/ns2016:DataSourceName)[1]','VARCHAR(250)')
    ) AS DataSourceName,
    COALESCE(
        xmlcolumn2010.value('(ns2010:Query/ns2010:CommandText)[1]','VARCHAR(2500)'),
        xmlcolumn2016.value('(ns2016:Query/ns2016:CommandText)[1]','VARCHAR(2500)')
    ) AS CommandText,
    reportXML
FROM (  
    SELECT 
        C.Name,
        c.Path,
        CONVERT(XML,CONVERT(VARBINARY(MAX),C.Content)) AS reportXML
    FROM  ReportServer.dbo.Catalog C
    WHERE  C.Content is not null
    AND  C.Type = 2
) CATDATA 
OUTER APPLY reportXML.nodes('/ns2010:Report/ns2010:DataSets/ns2010:DataSet') xmltable2010 ( xmlcolumn2010 )
OUTER APPLY reportXML.nodes('/ns2016:Report/ns2016:DataSets/ns2016:DataSet') xmltable2016 ( xmlcolumn2016 )
WHERE xmlcolumn2010.exist('.') = 1 OR xmlcolumn2016.exist('.') = 1
ORDER BY CATDATA.Name

方案2:使用通配符忽略命名空间差异

适合仅需提取节点内容、不关注版本的场景,代码更简洁:

SELECT  
    CATDATA.Name AS ReportName,
    CATDATA.Path AS ReportPathLocation,
    xmlcolumn.value('(@Name)[1]', 'VARCHAR(250)') AS DataSetName,
    xmlcolumn.value('(*:Query/*:DataSourceName)[1]','VARCHAR(250)') AS DataSourceName,
    xmlcolumn.value('(*:Query/*:CommandText)[1]','VARCHAR(2500)') AS CommandText,
    reportXML
FROM (  
    SELECT 
        C.Name,
        c.Path,
        CONVERT(XML,CONVERT(VARBINARY(MAX),C.Content)) AS reportXML
    FROM  ReportServer.dbo.Catalog C
    WHERE  C.Content is not null
    AND  C.Type = 2
) CATDATA 
OUTER APPLY reportXML.nodes('/*:Report/*:DataSets/*:DataSet') xmltable ( xmlcolumn )
ORDER BY CATDATA.Name

内容的提问来源于stack exchange,提问作者ssou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 09:02:48