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

时间:2011-04-21 08:17:22

标签: sql xml tsql reporting-services xpath

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

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)

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


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)

PS我在stackoverflow代码格式化方面遇到了一些麻烦,所以我更换了&lt;和&gt;用<和>标记。对于那个很抱歉。

3 个答案:

答案 0 :(得分:4)

基于布雷特的博客([http://blogs.netconnex.com/2011/05/extracting-ssrs-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 

答案 1 :(得分:1)

这个简单的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代码中。

答案 2 :(得分:0)

我无法测试这是否有效,但它应该做你想要的。

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