我想用以下数据翻译XML文件:
<FlatData>
<Details1_Collection>
<Details1 Customer1="Customer" Total1="3" />
...
</Details1_Collection>
</FlatData>
我感兴趣的数据是每个Details1
中的属性及其值。问题是这些属性在我想翻译的每个XML文件中都不一定相同,我想要一个能够处理这些Details1
的通用XSL:
<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和JörnHorstmann的答案,并尝试将两者结合起来。我运行这个命令:
msxsl.exe -o output.xml input.xml transform.xsl
我认为阻碍的是输入文件中的namespace:
<Report Name="MyReport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="MyReport">
答案 0 :(得分:4)
由于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>
我想我会尝试清理它以使用lavinio建议的apply-templates
样式。还要感谢select="@*"
代码for-each
循环中的xmlns
代码。有趣的是要弄清楚为什么最初会将Reporting Manager报告转储,并将<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>
值设置为报告名称,而不是Jörn Horstmann。
当我改进这个XSL时,我会继续更新这个答案。
编辑这里是与命名空间无关的版本,因为对于Reporting Services的每个不同报告,显然会有不同的命名空间:
{{1}}
答案 1 :(得分:3)
您可以使用"@*"
来引用所有属性,例如:
<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>
答案 2 :(得分: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">
答案 3 :(得分:2)
此转换是否会提供您想要的结果?
<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>
答案 4 :(得分:0)
另一种写JörnHorstmann答案的方法(如果你需要使用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>
答案 5 :(得分:0)
可能是最简单的方法:
<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>