【问题标题】:Parsing SSRS Report XML on ReportServer Database在 ReportServer 数据库上解析 SSRS 报告 XML
【发布时间】:2015-12-02 12:57:48
【问题描述】:

这是报告 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> 

我想要做的是获取数据源的所有实例。经过几个小时的战斗,我意识到我必须使用多个命名空间并在我的 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 限制)。

--edit:我使用 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!

【问题讨论】:

  • 定义 不起作用.. 与顶部的 XML 示例相比,我看不出您的查询有任何明显问题
  • G.value 的结果对于顶部的结果为 NULL。在我添加命名空间之前,它们对于所有 XML 都是 NULL,但不是它们非常有选择性
  • 发布演示问题的示例 XML,即查询返回 NULL
  • 最上面的 XML 是问题.. 所有 G.value 列都返回 NULL

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


【解决方案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)

【讨论】:

  • 如果报表是使用不同版本的报表生成器等构建的,那么它的 XML 架构会改变吗?我认为这无关紧要,因为 XML 定义来自使用 2008 的 Reporting Services?当然这只是我的假设,对此我很乐意得到澄清
  • 看起来是这样,不同的命名空间来自不同版本的 SSRS。虽然我不是经验丰富的 SSRS 人员,但无法真正澄清此事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-29
  • 1970-01-01
相关资源
最近更新 更多