XSLT在SSRS报告(XSLT on SSRS report)

2019-07-30 22:02发布

我想,以翻译与类似下面的数据的XML文件:

<FlatData>
    <Details1_Collection>
        <Details1 Customer1="Customer" Total1="3" />
        ...
    </Details1_Collection>
</FlatData>

我感兴趣的数据是在每个属性和值Details1 。 问题是,这些属性并不一定要在我要翻译每个XML文件都一样的,我希望有一个通用的XSL,可以处理这样的Details1 ,因为这些:

<Details1 Customer1="Customer" Total1="3" />
<Details1 Name="Jim" Age="14" Weight="180" />
<Details1 Date="2009-07-27" Range="1-5" Option1="True" />

这些不同的Details1不会出现相同的源XML文件中,而是在不同的文件。 不过,我想使用相同的XSL每个。

我想我需要的东西,喜欢<xsl:value-of select="@attribute_name"/>但我该怎么把为@attribute_name当我不事先知道会有什么属性? 此外,我怎么捕捉到属性名称? 我想爆炸上面像源XML:

<Details1>
    <Customer1>Customer</Customer1>
    <Total1>3</Total1>
</Details1>

编辑:感谢您的答复! 我遇到了麻烦超过了下面的输出,但是:

<?xml version="1.0" encoding="UTF-8"?>
<FlatData>
<Details1_Collection></Details1_Collection>
</FlatData>

我都试过lavinio的和乔恩HORSTMANN的答案,以及试图将两者结合起来。 我运行以下命令:

msxsl.exe -o output.xml input.xml transform.xsl

我认为东西是获得的方式是一个命名空间中输入文件:

<Report Name="MyReport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="MyReport">

Answer 1:

有增加,因为Microsoft SQL报告服务2008年命名空间是输入XML的部分困难。 我起先不明白, <Report Name="MyReport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="MyReport">是这样一个重要的线。 感谢帕维尔Minaev的命名空间评论 。 以下XSL工作来提取我想要的数据:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="EXQC005">
  <xsl:output method="xml" indent="yes" encoding="utf-8"/>

  <xsl:template match="/">
    <xsl:for-each select="a:Report/a:FlatData/a:Details1_Collection/a:Details1">
      <xsl:element name="{name(.)}">
        <xsl:for-each select="@*">
          <xsl:element name="{name(.)}">
            <xsl:value-of select="."/>
          </xsl:element>
        </xsl:for-each>
      </xsl:element>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

我想我会尝试清理它使用的apply-templates风格, lavinio建议。 还要感谢乔恩HORSTMANN的select="@*"在代码中for-each循环。 为什么Reporting Services报表与最初倾销这将是有趣弄清楚xmlns设置报告,而不是一个名称值架构URL 。

我将继续为我完善这一XSL来更新这个答案。

编辑:这里有一个命名空间无关的版本,因为,从Reporting Services的每一个不同的报告,会有很明显是不同的命名空间:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="utf-8"/>

  <xsl:template match="/">
    <xsl:for-each select="*[local-name()='Report']/*[local-name()='FlatData']/*[local-name()='Details1_Collection']/*[local-name()='Details1']">
      <Details>
        <xsl:for-each select="@*">
          <xsl:element name="{name(.)}">
            <xsl:value-of select="."/>
          </xsl:element>
        </xsl:for-each>
      </Details>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>


Answer 2:

您可以使用"@*"指的是所有的属性,如这些例子:

  • <xsl:value-of select="@*"/>
  • <xsl:apply-templates select="@*"/>
  • <xsl:template match="@*">

所述<xsl:element name="">构建体可用于具有任意名称创建一个新的元件,所述功能name()local-name()将返回一个特定属性的名称。

做你想做的,可以尝试沿着这些路线的东西:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <FlatData>
            <Details1_Collection>
                <xsl:apply-templates select="FlatData/Details1_Collection/Details1"/>
            </Details1_Collection>
        </FlatData>
    </xsl:template>
    <xsl:template match="Details1">
        <Details1>
            <xsl:apply-templates select="@*"/>
        </Details1>
    </xsl:template>
    <xsl:template match="@*">
        <xsl:element name="{name()}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>


Answer 3:

为了解决这个命名空间问题(两个答案),增加一个命名空间声明带有前缀为您XLST:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:r="MyReport"
                version="1.0">

然后用它在你的所有XPath表达式资格元素,例如:

<xsl:template match="//r:Details1">


Answer 4:

这是否转型给你想要的结果呢?

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="xml" indent="yes" encoding="utf-8" />

    <xsl:template match="//Details1">
        <Details1>
            <xsl:for-each select="@*">
                <xsl:element name="{name(.)}"><xsl:value-of select="." /></xsl:element>
            </xsl:for-each>
        </Details1>
    </xsl:template>

</xsl:stylesheet>


Answer 5:

另一种方式来写乔恩HORSTMANN的回答(如果你需要点评详情,Details2要做到这一点,等等...)将是:

<xsl:template match="//Details1 | //Details2 | //whatever">
  <xsl:copy>
    <xsl:apply-templates select="@*"/>
  </xsl:copy>
</xsl:template>

<xsl:template match="@*">
  <xsl:element name="{name(.)}">
    <xsl:value-of select="." />
  </xsl:element>
</xsl:template>


Answer 6:

也许最简单的方式做到这一点:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output indent="yes"/>

  <xsl:template match="/">
    <FlatData>
      <xsl:copy-of select="//Details1" />
    </FlatData>
  </xsl:template>
</xsl:stylesheet>


文章来源: XSLT on SSRS report