将 SSRS 报表 XML 中的根报表节点更新为包括 rd 节点

Update root Report node in SSRS report XML to include rd node

提问人:svenGUTT 提问时间:9/9/2023 更新时间:9/9/2023 访问量:30

问:

我有一个 powershell 脚本,我们运行该脚本来更新整个目录的 RDL 文件,方法是将其连接字符串从共享更改为嵌入,并向每个参数添加 Hidden = True 标记。

这一直很好,直到我们最近遇到一份较旧的报告。连接更新的一部分是将“安全类型”从“无”设置为“数据库”。我发现,在这几个实例中,它没有更新 SecurityType 节点,而是添加了一个全新的实例,导致报表在报表生成器中打开时出错。

在检查 XML 时,我注意到根节点中只有默认命名空间,它不包含 rd 引用。但是,SecurityTYpe 节点是使用 rd 引用设置的...当 powershell 命中此节点时,它无法读取它,并且它认为没有 SecurityType 节点,因此它写入了一个新的节点。 这是有问题的根节点...

<Report xmlns="http://schemas.microsoft.com/sqlserver/reporting/2008/01/reportdefinition">

这是 SecurityType 节点在同一报告中的样子:

<rd:SecurityType xmlns:rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner">None</rd:SecurityType>

如果我手动将 rd 命名空间添加到“报表”节点,则 powershell 工作正常。所以我想知道如何将其更新为:

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

这是 PS 脚本(使用 System.Xml.Linq)获取 xml 和命名空间的方式:

    $ns = $doc.Root.GetDefaultNamespace()
    $rd = $doc.Root.GetNamespaceOfPrefix("rd");
    $p1 = $doc.Root.GetNamespaceOfPrefix("p1");

然后,我们遍历 DataSource 节点以获取其不同的元素:

    foreach($dataSource in $dataSources)
    {
        $dataSourceName = $dataSource.FirstAttribute.Value      
        $securityType = $dataSource.Element($rd + "SecurityType")
        $securityTypeVal = $securityType.Value
...

不过,正是在这里,设置$securityType和$securityTypeVal都出现了问题......即使它们确实存在,它们也会返回 NULL。

        if($securityType -eq $null)
        {
            $dataSource.Add([System.Xml.Linq.XElement]::new($rd + [System.Xml.Linq.XName]::get('SecurityType'),'Database'))
        }
        else
        {
            if($securityTypeVal -ne "Database")
            {
                $securityType.SetValue('Database')
                $securityTypeVal = $dataSource.Element($rd + "SecurityType").Value
            }
        }   

在尝试处理 SecurityType 时,我应该考虑根中缺少的 rd 命名空间前缀吗?或者有没有办法查看它是否存在,如果缺少它,请添加它?我一直在尝试各种拼凑的方法来添加它,但我远非这种语言的专家,我所做的一切都导致了各种错误。我感谢任何帮助。

XML LINQ Reporting-Services 报表 RDL

评论

0赞 jdweng 9/9/2023
XML 无效。向生成无效 XML 的人员报告问题。
0赞 svenGUTT 9/12/2023
问题是,这是历史数据,将报表RDL / XML作为二进制文件保存在其中一个数据库表中,我们无法真正更新它。我们需要能够反复识别这些情况,并在它们出现时进行处理。有没有一种快速的方法可以简单地查看该根报告并确定 rd 命名空间是否存在?我能够使用 ContentXML.value('namespace-uri((/*)[1])','nvarchar(max)') 来拉取默认的 ns,而不是对 xml 的交叉应用,但即使在带有 rd 前缀的有效 xml 上,我也无法确定如何拉取前缀。
0赞 jdweng 9/12/2023
xml 解析立即失败。我认为将XmlReader与XmlReaderSettings一起使用可以检测错误。设置 XmlReader 设置以处理错误。Xml Linq 将使用 XmlReader。我通常会在 c# 中处理这样的东西,然后转换为 powershell。您不能使用网络库编辑无效的 xml。您需要使用正则表达式进行编辑。
0赞 svenGUTT 9/12/2023
我的坏...我有点掩盖了我自己的 OP,因为它正在处理 PS。如果我只想在 SQL 中查找 rd 前缀(在任何 PS 脚本运行之前都已完成),是否有一个简单的 XQuery 来提取它?如前所述,我只能将默认值拉到这一点。如果我们能在从数据库中提取 rdl 详细信息时将它们扼杀在萌芽状态,那么我什至不必处理它们。我整个上午都在寻找我认为是一个简单的命令,但我找到的一切都比我需要的要先进得多,而且没有任何东西涵盖我正在寻找的东西。
0赞 jdweng 9/12/2023
我认为唯一可靠的方法是读取文件并处理异常。如果未收到异常,则表示库捕获了错误,并且可能会得到一个 null 对象。然后,您需要做的就是检查对象是否为空(或不包含任何元素)。

答: 暂无答案