T-SQL 从 RDL 数据中选择所有 XML 节点作为行

Posted

技术标签:

【中文标题】T-SQL 从 RDL 数据中选择所有 XML 节点作为行【英文标题】:T-SQL select all XML nodes as rows from RDL data 【发布时间】:2011-08-10 03:03:05 【问题描述】:

我正在尝试从包含 XML 列的表中进行选择。我想获取特定节点并为每个节点创建一行。

XML 直接从 Reporting Services 数据库中获取,包含 RDL(报告)结构。我的目标是显示每个报告的所有 ‹Textbox›‹Value›example‹/Value›‹/Textbox› 值。 ‹Textbox› 节点的位置是不可预测的(它可以是 XML 结构中某处任何元素的一部分)。

以下是当前代码,但由于某种原因 id 不起作用:


IF object_id('tempdb..#c') IS NOT NULL
   DROP TABLE #c

select top 50
     path as reportpath
    ,name as reportname
    ,convert(xml, convert(varbinary(max), content)) as reportxml
into
    #c  
from 
    reportserver.dbo.catalog
where 
    content is not null
order by creationdate desc

-----------------------------------------
DECLARE @x XML
SELECT @x = 
( SELECT 
     [reportpath]
    ,[reportname]
    ,[reportxml].query('
            for $a in //../Textbox
            return ‹Textbox
            valueX="$a/Value"
            /›
        ')
  FROM #c AS reports 
  FOR XML AUTO
)
select @x
-----------------------------------------
SELECT [reportpath]    = T.Item.value('../@reportpath', 'nvarchar(max)'),
       [reportname]    = T.Item.value('../@reportname', 'nvarchar(max)'),
       value     = T.Item.value('@value' , 'nvarchar(max)')
FROM   @x.nodes('//reports/Textbox') AS T(Item)

下面的示例显示了包含“值”的示例“文本框”:


          ‹RowGrouping›
            ‹Width›2.53968cm‹/Width›
            ‹DynamicRows›
              ‹Grouping Name="matrix1_OperationalWeek2"›
                ‹GroupExpressions›
                  ‹GroupExpression›=Fields!OperationalWeek.Value‹/GroupExpression›
                ‹/GroupExpressions›
              ‹/Grouping›
              ‹ReportItems›
                ‹Textbox Name="textbox35"›
                  ‹rd:DefaultName›textbox35‹/rd:DefaultName›
                  ‹Style›
                    ‹BackgroundColor›White‹/BackgroundColor›
                    ‹PaddingLeft›2pt‹/PaddingLeft›
                    ‹PaddingRight›2pt‹/PaddingRight›
                    ‹PaddingTop›2pt‹/PaddingTop›
                    ‹PaddingBottom›2pt‹/PaddingBottom›
                  ‹/Style›
                  ‹ZIndex›8‹/ZIndex›
                  ‹Value›=Fields!OperationalWeek.Value‹/Value›
                ‹/Textbox›
              ‹/ReportItems›
            ‹/DynamicRows›
          ‹/RowGrouping›

PS 我在 *** 代码格式方面遇到了一些问题,所以我用 ‹ 和 › 替换了 标记。对于那个很抱歉。

【问题讨论】:

【参考方案1】:

基于 Bret 的博客 ([http://blogs.netconnex.com/2011/05/extracting-s-s-rs-report-rdl-xml-from.html][1]) 并添加命名空间会给你带来结果......我希望我可以声称我理解得足以解释,但我主要是通过“绊倒”它来找到我的方式。

--============================================== ===

;WITH XMLNAMESPACES (
DEFAULT 'http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition',
'http://schemas.microsoft.com/SQLServer/reporting/reportdesigner' AS rd --ReportDefinition
)
select top 50 
     c.Path as reportpath 
    --, c.name as reportname 
    ,t.value('@Name','VARCHAR(100)') as TextboxName
    ,t.value('data(Paragraphs/Paragraph/TextRuns/TextRun/Value)[1]', 'varchar(max)') as value 
from  
    reportserver.dbo.catalog c
cross apply 
    (select convert(xml, convert(varbinary(max), content))) as R(reportxml) 
cross apply 
--Get all the Query elements (The "*:" ignores any xml namespaces) 
    r.reportxml.nodes('//*:Textbox') n(t)        
where  
    content is not null 
    and c.Type = 2 -- Reports
order by creationdate desc 

【讨论】:

【参考方案2】:

这个简单的 XQuery

for $a in //Textbox             
 return 
   <Textbox             
      valueX="$a/Value"             
   /> 

应用于提供的 XML 文档时(添加命名空间定义以使其格式正确):

<RowGrouping xmlns:rd="rd">
  <Width>2.53968cm</Width>
  <DynamicRows>
    <Grouping Name="matrix1_OperationalWeek2">
      <GroupExpressions>
        <GroupExpression>=Fields!OperationalWeek.Value</GroupExpression>
      </GroupExpressions>
    </Grouping>
    <ReportItems>
      <Textbox Name="textbox35">
        <rd:DefaultName>textbox35</rd:DefaultName>
        <Style>
          <BackgroundColor>White</BackgroundColor>
          <PaddingLeft>2pt</PaddingLeft>
          <PaddingRight>2pt</PaddingRight>
          <PaddingTop>2pt</PaddingTop>
          <PaddingBottom>2pt</PaddingBottom>
        </Style>
        <ZIndex>8</ZIndex>
        <Value>=Fields!OperationalWeek.Value</Value>
      </Textbox>
    </ReportItems>
  </DynamicRows>
</RowGrouping>

产生想要的正确结果:

<?xml version="1.0" encoding="UTF-8"?>
<Textbox valueX="=Fields!OperationalWeek.Value"/>

因此,如果您无法获得结果,那么您的问题出在其他问题上,而不是在 XQuery 代码中。

【讨论】:

谢谢。不幸的是,我仍然无法找到错误。我的代码不返回任何“文本框”信息。也许它与编码有关,我还不确定如何解决这个问题......【参考方案3】:

我无法测试这是否有效,但它应该可以满足您的需求。

select top 50
     path as reportpath
    ,name as reportname
    ,n.t.value('Value[1]', 'varchar(max)') as value
from 
    reportserver.dbo.catalog
cross apply
    (select convert(xml, convert(varbinary(max), content))) as c(reportxml)
cross apply
    c.reportxml.nodes('//Textbox') n(t)       
where 
    content is not null
order by creationdate desc

【讨论】:

不幸的是它返回 0 行。也许是某种转换问题或与 XML 结构有关的问题……我仍在努力寻找解决方案

以上是关于T-SQL 从 RDL 数据中选择所有 XML 节点作为行的主要内容,如果未能解决你的问题,请参考以下文章

从数据库中检索已删除的 RDL 文件

如何在 VS2003 中突出显示 rdl 项目的 xml 视图?

如何从离散的 varchar 元素中选择 xml?

使用 T-SQL 将表转换为 XML

如何在 Visual Studio 中打开 .rdl 文件?

从选定节点中选择返回数据所有xml