Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于多个SSRS报告的统一xslt(xml导出)_Xml_Xslt_Reporting Services_Ssrs 2016 - Fatal编程技术网

用于多个SSRS报告的统一xslt(xml导出)

用于多个SSRS报告的统一xslt(xml导出),xml,xslt,reporting-services,ssrs-2016,Xml,Xslt,Reporting Services,Ssrs 2016,我有SSRS 2016和一些报告(结构相似但名称和数据不同)要在xml导出期间转换 报表xml示例: <?xml version="1.0" encoding="utf-8"?> <Report xsi:schemaLocation="My_Report_1 http://..." Name="My_Report_1" xmlns:xsi="http://www.w3.org/20

我有SSRS 2016和一些报告(结构相似但名称和数据不同)要在xml导出期间转换

报表xml示例:

<?xml version="1.0" encoding="utf-8"?>
<Report xsi:schemaLocation="My_Report_1 http://..." Name="My_Report_1"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="My_Report_1">
    <Table>
        <tbl_MainGroup_Collection>
            <Data TxDev="abc" DateTime="20200906001057" DBVersion="1.0" ProductVersion="1.0" Version="1.0">
                <tbl_SiteGroup_Collection>
                    <Site SiteName="All sites">
                        <tbl_ColumnGroup_Collection>
                            <Column Column1="Week 33" Column2="Week 34">
                                <Lines>
                                    <Line LineName="abc" Column1="0.00" Column2="0.00" LineNumber="1" EntityType="0" EntityNo="1" />
                                    <Line LineName="dfg" LineNumber="-1" EntityType="0" EntityNo="2" />
                                </Lines>
                            </Column>
                        </tbl_ColumnGroup_Collection>
                    </Site>
                </tbl_SiteGroup_Collection>
            </Data>
        </tbl_MainGroup_Collection>
    </Table>
</Report>

XSLT转换示例:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<xsl:stylesheet version="1.0"     
    xmlns:x="My_Report_1"
    exclude-result-prefixes="x"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output omit-xml-declaration="no" indent="yes" method="xml" />
    
  <xsl:template match="x:Report|x:Table|x:tbl_MainGroup_Collection">
      <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="x:Report/x:Table//x:Data">
    <Data TxDev="{@TxDev}" DateTime="{@DateTime}" DBVersion="{@DBVersion}" ProductVersion="{@ProductVersion}" Version="{@Version}">
      <xsl:apply-templates select="x:tbl_SiteGroup_Collection"/>
    </Data>
  </xsl:template>

  <xsl:template match="x:tbl_SiteGroup_Collection">
    <Sites>
      <xsl:apply-templates select="x:Site"/>
    </Sites>
  </xsl:template>

  <xsl:template match="x:Site">
    <Site SiteNumber="{@SiteNumber}" SiteID="{@SiteID}" SiteName="{@SiteName}">
      <xsl:apply-templates select="x:tbl_ColumnGroup_Collection"/>
    </Site>
  </xsl:template>

  <xsl:template match="x:tbl_ColumnGroup_Collection">
    <Columns>
      <xsl:apply-templates select="x:Column"/>
    </Columns>
  </xsl:template>

  <xsl:template match="x:Column">
    <xsl:for-each select="@*[starts-with(local-name(), 'Column')]">
      <Column ColumnNumber="{translate(local-name(),'Column','')}" ColumnName="{.}">
        <xsl:variable name="attrName" select="local-name()"/>
        <xsl:for-each select="../x:Lines">
          <xsl:call-template name="Lines">
            <xsl:with-param name="ColumnName" select="$attrName"/>
          </xsl:call-template>
        </xsl:for-each>
      </Column>
    </xsl:for-each>
  </xsl:template>

  <xsl:template name="Lines" match="x:Lines">
    <xsl:param name="ColumnName"/>
    <Lines>
      <xsl:for-each select="x:Line[@LineNumber&gt;0 and @EntityType=0]">
        <xsl:sort select="@LineNumber" data-type="number" />
        <xsl:call-template name="Line">
          <xsl:with-param name="ColumnName" select="$ColumnName"/>
        </xsl:call-template>
      </xsl:for-each>
    </Lines>
  </xsl:template>

  <xsl:template name="Line" match="x:Line">
    <xsl:param name="ColumnName"/>
    <Line LineNumber="{@LineNumber}" LineName="{@LineName}" >
      <xsl:variable name="LineNo" select="@LineNumber"/>
      <xsl:choose>
        <xsl:when test="count(../x:Line[@LineNumber=$LineNo and @EntityType=1])>0">
          <xsl:attribute name="Value">
            <xsl:value-of select="@*[local-name()=$ColumnName]"/>
          </xsl:attribute>
          <Departments>
            <xsl:for-each select="../x:Line[@LineNumber=$LineNo and @EntityType=1]">
              <xsl:sort select="@EntityNo" data-type="number"/>
              <Department DepNumber="{@EntityNo}" DepName="{@LineName}" Value="{@*[local-name()=$ColumnName]}">
              </Department>
            </xsl:for-each>
          </Departments>
        </xsl:when>
        <xsl:when test="count(../x:Line[@LineNumber=$LineNo and @EntityType=2])>0">
          <xsl:if test="@*[local-name()=$ColumnName]">
            <xsl:attribute name="Value">
              <xsl:value-of select="@*[local-name()=$ColumnName]"/>
            </xsl:attribute>
          </xsl:if>
          <MOPs>
            <xsl:for-each select="../x:Line[@LineNumber=$LineNo and @EntityType=2]">
              <xsl:sort select="@EntityNo" data-type="number"/>
              <MOP MOPNumber="{@EntityNo}" MOPName="{@LineName}" Value="{@*[local-name()=$ColumnName]}">
              </MOP>
            </xsl:for-each>
          </MOPs>
        </xsl:when>
        <xsl:otherwise>
          <xsl:attribute name="Value">
            <xsl:value-of select="@*[local-name()=$ColumnName]"/>
          </xsl:attribute>
        </xsl:otherwise>
      </xsl:choose>
    </Line>
  </xsl:template>

  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>

</xsl:stylesheet>

由于名称空间绑定xmlns:x=“My_Report_1”,我只能将此xslt转换用于此报告。是否有任何方法可以生成更通用的xslt转换,以处理所有此类报告,而不考虑名称空间uri的值?是否为命名空间值提供参数


提前感谢。

来自OP的评论:

例如,我想在XSLT中传递某种变量或函数 示例
。 -昨天

一个甚至不需要将名称空间uri作为参数传递的通用解决方案是:

在每个XPath表达式中替换(在XSLT代码中)

*[local-name() = 'someElementName']

在提供的代码上执行此操作将导致此转换

请注意,现在不必要的前缀为
x:
的命名空间声明已被删除

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

  <xsl:output omit-xml-declaration="no" indent="yes" method="xml" />

  <xsl:template match="*[local-name()= 'Report']| *[local-name()= 'Table']| *[local-name()= 'tbl_MainGroup_Collection']">
      <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="*[local-name()= 'Report']/*[local-name()= 'Table']//*[local-name()= 'Data']">
    <Data TxDev="{@TxDev}" DateTime="{@DateTime}" DBVersion="{@DBVersion}" ProductVersion="{@ProductVersion}" Version="{@Version}">
      <xsl:apply-templates select="*[local-name()= 'tbl_SiteGroup_Collection']"/>
    </Data>
  </xsl:template>

  <xsl:template match="*[local-name()= 'tbl_SiteGroup_Collection']">
    <Sites>
      <xsl:apply-templates select="*[local-name()= 'Site']"/>
    </Sites>
  </xsl:template>

  <xsl:template match="*[local-name()= 'Site']">
    <Site SiteNumber="{@SiteNumber}" SiteID="{@SiteID}" SiteName="{@SiteName}">
      <xsl:apply-templates select="*[local-name()= 'tbl_ColumnGroup_Collection']"/>
    </Site>
  </xsl:template>

  <xsl:template match="*[local-name()= 'tbl_ColumnGroup_Collection']">
    <Columns>
      <xsl:apply-templates select="*[local-name()= 'Column']"/>
    </Columns>
  </xsl:template>

  <xsl:template match="*[local-name()='Column']">
    <xsl:for-each select="@*[starts-with(local-name(), 'Column')]">
      <Column ColumnNumber="{translate(local-name(),'Column','')}" ColumnName="{.}">
        <xsl:variable name="attrName" select="local-name()"/>
        <xsl:for-each select="../*[local-name()='Lines']">
          <xsl:call-template name="Lines">
            <xsl:with-param name="ColumnName" select="$attrName"/>
          </xsl:call-template>
        </xsl:for-each>
      </Column>
    </xsl:for-each>
  </xsl:template>

  <xsl:template name="Lines" match="*[local-name()='Lines']">
    <xsl:param name="ColumnName"/>
    <Lines>
      <xsl:for-each select="*[local-name()='Line'][@LineNumber&gt;0 and @EntityType=0]">
        <xsl:sort select="@LineNumber" data-type="number" />
        <xsl:call-template name="Line">
          <xsl:with-param name="ColumnName" select="$ColumnName"/>
        </xsl:call-template>
      </xsl:for-each>
    </Lines>
  </xsl:template>

  <xsl:template name="Line" match="*[local-name()='Line']">
    <xsl:param name="ColumnName"/>
    <Line LineNumber="{@LineNumber}" LineName="{@LineName}" >
      <xsl:variable name="LineNo" select="@LineNumber"/>
      <xsl:choose>
        <xsl:when test="count(../*[local-name()='Line'][@LineNumber=$LineNo and @EntityType=1])>0">
          <xsl:attribute name="Value">
            <xsl:value-of select="@*[local-name()=$ColumnName]"/>
          </xsl:attribute>
          <Departments>
            <xsl:for-each select="../*[local-name()='Line'][@LineNumber=$LineNo and @EntityType=1]">
              <xsl:sort select="@EntityNo" data-type="number"/>
              <Department DepNumber="{@EntityNo}" DepName="{@LineName}" Value="{@*[local-name()=$ColumnName]}">
              </Department>
            </xsl:for-each>
          </Departments>
        </xsl:when>
        <xsl:when test="count(../*[local-name()='Line'][@LineNumber=$LineNo and @EntityType=2])>0">
          <xsl:if test="@*[local-name()=$ColumnName]">
            <xsl:attribute name="Value">
              <xsl:value-of select="@*[local-name()=$ColumnName]"/>
            </xsl:attribute>
          </xsl:if>
          <MOPs>
            <xsl:for-each select="../*[local-name()='Line'][@LineNumber=$LineNo and @EntityType=2]">
              <xsl:sort select="@EntityNo" data-type="number"/>
              <MOP MOPNumber="{@EntityNo}" MOPName="{@LineName}" Value="{@*[local-name()=$ColumnName]}">
              </MOP>
            </xsl:for-each>
          </MOPs>
        </xsl:when>
        <xsl:otherwise>
          <xsl:attribute name="Value">
            <xsl:value-of select="@*[local-name()=$ColumnName]"/>
          </xsl:attribute>
        </xsl:otherwise>
      </xsl:choose>
    </Line>
  </xsl:template>

  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>

</xsl:stylesheet>

在提供的源XML文档上应用此转换将产生与原始转换完全相同的输出


警告:只有在保证引用的本地元素名称不会与多个(不同)命名空间一起使用时,此解决方案才是正确的。

如果所有报表都在同一命名空间中,请对所有报表使用同一命名空间URI。源报表使用的命名空间由什么决定?是否存在已知的可能名称空间列表?--另外,看起来您正试图创建一个涵盖所有可能输入的大型通用XSLT。在大多数情况下,为每种类型创建(和维护)一个单独的XSLT要简单得多。SSRS导出到xml会生成名称空间为xmlns=“My_Report_1”的标记,XSLT中的名称空间必须精确。这已在中描述。例如,我想要的是在XSLT中传递某种变量或函数。正是我想要的)谢谢,@Dimitre!
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output omit-xml-declaration="no" indent="yes" method="xml" />

  <xsl:template match="*[local-name()= 'Report']| *[local-name()= 'Table']| *[local-name()= 'tbl_MainGroup_Collection']">
      <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="*[local-name()= 'Report']/*[local-name()= 'Table']//*[local-name()= 'Data']">
    <Data TxDev="{@TxDev}" DateTime="{@DateTime}" DBVersion="{@DBVersion}" ProductVersion="{@ProductVersion}" Version="{@Version}">
      <xsl:apply-templates select="*[local-name()= 'tbl_SiteGroup_Collection']"/>
    </Data>
  </xsl:template>

  <xsl:template match="*[local-name()= 'tbl_SiteGroup_Collection']">
    <Sites>
      <xsl:apply-templates select="*[local-name()= 'Site']"/>
    </Sites>
  </xsl:template>

  <xsl:template match="*[local-name()= 'Site']">
    <Site SiteNumber="{@SiteNumber}" SiteID="{@SiteID}" SiteName="{@SiteName}">
      <xsl:apply-templates select="*[local-name()= 'tbl_ColumnGroup_Collection']"/>
    </Site>
  </xsl:template>

  <xsl:template match="*[local-name()= 'tbl_ColumnGroup_Collection']">
    <Columns>
      <xsl:apply-templates select="*[local-name()= 'Column']"/>
    </Columns>
  </xsl:template>

  <xsl:template match="*[local-name()='Column']">
    <xsl:for-each select="@*[starts-with(local-name(), 'Column')]">
      <Column ColumnNumber="{translate(local-name(),'Column','')}" ColumnName="{.}">
        <xsl:variable name="attrName" select="local-name()"/>
        <xsl:for-each select="../*[local-name()='Lines']">
          <xsl:call-template name="Lines">
            <xsl:with-param name="ColumnName" select="$attrName"/>
          </xsl:call-template>
        </xsl:for-each>
      </Column>
    </xsl:for-each>
  </xsl:template>

  <xsl:template name="Lines" match="*[local-name()='Lines']">
    <xsl:param name="ColumnName"/>
    <Lines>
      <xsl:for-each select="*[local-name()='Line'][@LineNumber&gt;0 and @EntityType=0]">
        <xsl:sort select="@LineNumber" data-type="number" />
        <xsl:call-template name="Line">
          <xsl:with-param name="ColumnName" select="$ColumnName"/>
        </xsl:call-template>
      </xsl:for-each>
    </Lines>
  </xsl:template>

  <xsl:template name="Line" match="*[local-name()='Line']">
    <xsl:param name="ColumnName"/>
    <Line LineNumber="{@LineNumber}" LineName="{@LineName}" >
      <xsl:variable name="LineNo" select="@LineNumber"/>
      <xsl:choose>
        <xsl:when test="count(../*[local-name()='Line'][@LineNumber=$LineNo and @EntityType=1])>0">
          <xsl:attribute name="Value">
            <xsl:value-of select="@*[local-name()=$ColumnName]"/>
          </xsl:attribute>
          <Departments>
            <xsl:for-each select="../*[local-name()='Line'][@LineNumber=$LineNo and @EntityType=1]">
              <xsl:sort select="@EntityNo" data-type="number"/>
              <Department DepNumber="{@EntityNo}" DepName="{@LineName}" Value="{@*[local-name()=$ColumnName]}">
              </Department>
            </xsl:for-each>
          </Departments>
        </xsl:when>
        <xsl:when test="count(../*[local-name()='Line'][@LineNumber=$LineNo and @EntityType=2])>0">
          <xsl:if test="@*[local-name()=$ColumnName]">
            <xsl:attribute name="Value">
              <xsl:value-of select="@*[local-name()=$ColumnName]"/>
            </xsl:attribute>
          </xsl:if>
          <MOPs>
            <xsl:for-each select="../*[local-name()='Line'][@LineNumber=$LineNo and @EntityType=2]">
              <xsl:sort select="@EntityNo" data-type="number"/>
              <MOP MOPNumber="{@EntityNo}" MOPName="{@LineName}" Value="{@*[local-name()=$ColumnName]}">
              </MOP>
            </xsl:for-each>
          </MOPs>
        </xsl:when>
        <xsl:otherwise>
          <xsl:attribute name="Value">
            <xsl:value-of select="@*[local-name()=$ColumnName]"/>
          </xsl:attribute>
        </xsl:otherwise>
      </xsl:choose>
    </Line>
  </xsl:template>

  <xsl:template match="/">
    <xsl:apply-templates />
  </xsl:template>

</xsl:stylesheet>