在ReportServer数据库上解析SSRS报告XML

时间:2015-12-02 12:57:49

标签: sql-server xml reporting-services ssrs-2008

这是报告XML的首要部分:

<Report xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner" xmlns:cl="http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition">
  <AutoRefresh>0</AutoRefresh>
  <DataSources>
    <DataSource Name="DataSource1">
      <DataSourceReference>Live Data</DataSourceReference>
      <rd:SecurityType>None</rd:SecurityType>
      <rd:DataSourceID>827954ef-81fc-4a34-8f40-5354265d867b</rd:DataSourceID>
    </DataSource>
  </DataSources>
</Report> 

我要做的是获取DataSources的所有实例。经过几个小时的战斗,我意识到我必须使用多个命名空间并在我的select语句之前引用它们。这是我现在的询问:

;WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition' AS ns, 'http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition' AS cl, 'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' AS rd)
SELECT
    c.*,
    CAST( CONVERT(VARBINARY(MAX), c.Content) AS XML),
    G.value('ns:DataSource[1]/rd:SecurityType[1]', 'NVARCHAR(MAX)') AS 'SecurityType',
    G.value('ns:DataSource[1]/ns:DataSourceReference[1]', 'NVARCHAR(MAX)') AS 'DataSourceReference',
    G.value('ns:DataSource[1]/rd:DataSourceID[1]', 'NVARCHAR(MAX)') AS 'DataSourceID'
FROM Catalog c
    OUTER APPLY (SELECT CAST( CONVERT(VARBINARY(MAX), c.Content) AS XML)) as Content(c)
    OUTER APPLY Content.c.nodes('//ns:DataSources') AS DS(G)
WHERE c.Type NOT IN (5, 4)

现在我非常困惑,因为它只适用于少量XML。我知道有另一种方法来提取该信息(我相信使用local-name())但我不仅希望它(无论如何可能)使它工作,而且还要理解为什么它不能以当前的形式工作(如果它不只是缺乏知识,而是SQL / XML克制。)

- 编辑:我使用OUTER APPLY获取所有不起作用的NULL,一旦我知道查询是现场,我会将其更改为CROSS

为了进行比较,这是XML的开头,查询返回正确的值:

<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition" xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">   
  <DataSources>
    <DataSource Name="DataSource1">
      <DataSourceReference>Live Data</DataSourceReference>
      <rd:SecurityType>None</rd:SecurityType>
      <rd:DataSourceID>956f67a3-7d7b-46cd-acb2-0e6490d0d33a</rd:DataSourceID>
    </DataSource>
  </DataSources>

我会永远感激任何帮助理解上述问题。

PS。我讨厌SQL中的XML!

1 个答案:

答案 0 :(得分:1)

XML中的默认名称空间URI是:

xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition"

在查询开始时,您有一个不同的URI映射到前缀ns

'http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition' AS ns

这可能是问题所在。如果您在不同的XML文档中有不同的命名空间,则无法避免使用local-name()忽略命名空间,例如:

;WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/reporting/2010/01/componentdefinition' AS cl, 'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' AS rd)
SELECT
    c.*,
    CAST( CONVERT(VARBINARY(MAX), c.Content) AS XML),
    G.value('*[local-name()="DataSource"][1]/rd:SecurityType[1]', 'NVARCHAR(MAX)') AS 'SecurityType',
    G.value('*[local-name()="DataSource"][1]/*[local-name()="DataSourceReference"][1]', 'NVARCHAR(MAX)') AS 'DataSourceReference',
    G.value('*[local-name()="DataSource"][1]/rd:DataSourceID[1]', 'NVARCHAR(MAX)') AS 'DataSourceID'
FROM Catalog c
    OUTER APPLY (SELECT CAST( CONVERT(VARBINARY(MAX), c.Content) AS XML)) as Content(c)
    OUTER APPLY Content.c.nodes('//*[local-name()="DataSources"]') AS DS(G)
WHERE c.Type NOT IN (5, 4)
相关问题