XSLT在SSRS报告
我想通过类似以下的数据转换为XML文件:XSLT在SSRS报告
<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。
我在想我需要像<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
我认为东西是获得的方式是在输入文件中的namespace:
<Report Name="MyReport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="MyReport">
由于Microsoft SQL Reporting Services 2008名称空间是输入XML的一部分,因此增加了难度。起初我并没有意识到<Report Name="MyReport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="MyReport">
是如此重要的一条线。感谢Pavel Minaev的namespace comment。以下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建议。对于for-each
循环中的select="@*"
代码,还要感谢Jörn Horstmann。找出为什么Reporting Services报告最初倾倒的原因是xmlns
的值设置为报告的名称,而不是schema 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>
您可以使用"@*"
指所有的属性,如这些例子:
<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>
这是否转化给你想要的结果呢?
<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>
另一种方式来写乔恩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>
可能做到这一点最简单的方法:
<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">
这将导致一个XML文件几乎一样多的行原始的,输入XML,但全部为空,保存第一行包含``。 – 2009-07-28 16:02:28
原来,由于名称空间问题,我得到了一个空行而不是我想要的数据;更新的问题,添加了我自己的答案。 – 2009-07-28 17:17:23