Xml SSRS报告中的XSLT

Xml SSRS报告中的XSLT,xml,xslt,reporting-services,xml-attribute,Xml,Xslt,Reporting Services,Xml Attribute,我想转换包含以下数据的XML文件: <FlatData> <Details1_Collection> <Details1 Customer1="Customer" Total1="3" /> ... </Details1_Collection> </FlatData> 这些不同的细节1不会出现在同一个源XML文件中,而是出现在不同的文件中。但是,我希望在每个应用程序上使用相同的XSL 我

我想转换包含以下数据的XML文件:

<FlatData>
    <Details1_Collection>
        <Details1 Customer1="Customer" Total1="3" />
        ...
    </Details1_Collection>
</FlatData>
这些不同的
细节1
不会出现在同一个源XML文件中,而是出现在不同的文件中。但是,我希望在每个应用程序上使用相同的XSL

我想我需要像
这样的东西,但是当我事先不知道会有什么属性时,我应该为
@attribute\u name
放些什么呢?另外,如何捕获属性名称?我想将上面的源XML分解为如下内容:

<Details1>
    <Customer1>Customer</Customer1>
    <Total1>3</Total1>
</Details1>
我认为在输入文件中有一个障碍:

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

您可以使用
“@*”
引用所有属性,如以下示例:

构造可用于创建具有任意名称的新元素,函数
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>

此转换是否给出您想要的结果

<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>

另一种写Jörn Horstmann答案的方法(如果你需要用Details1、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>

可能是最简单的方法:

<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>

要解决名称空间问题(对于两种答案),请在XLST中添加带有前缀的名称空间声明:

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

然后在所有XPath表达式中使用它来限定元素,例如:

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

由于Microsoft SQL Reporting Services 2008命名空间是输入XML的一部分,因此难度增加。起初我没有意识到
是一条如此重要的线路。感谢帕维尔·米纳耶夫的支持。以下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>

这导致一个XML文件的行数几乎与原始输入XML的行数相同,但所有行都是空的,只保留包含
的第一行;更新了问题,添加了我自己的答案。不是真的-这只是复制元素的原样,问题是关于将属性转换为元素。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:r="MyReport"
                version="1.0">
<xsl:template match="//r:Details1">
<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>
<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>