Fun*_*arn 1 xslt loops nested dynamic
我是StackOverflow的新用户,因此,如果我无意违反了任何论坛规则,请原谅我。
我正在从Cognos获取XML文档输出,我希望将其用作Crystal报表的输入。但是,Crystal Report所需的XML格式与Cognos输出的XML格式不同。
我正在尝试使用XSLT转换输入XML文档(Cognos),以获取Crystal所需的XML。
设置了上下文之后,下面是来自Cognos的Input XML:
<?xml version="1.0"?>
<dataset>
<metadata>
<item Name="EmpId" />
<item Name="EmpName" />
<item Name="DeptName" />
</metadata>
<data>
<rows>
<row>
<value>1</value>
<value>John</value>
<value>Finance</value>
</row>
<row>
<value>2</value>
<value>Peter</value>
<value>Admin</value>
</row>
</rows>
</data>
Run Code Online (Sandbox Code Playgroud)
Crystal Report所需的XML格式:
<?xml version="1.0"?>
<dataset>
<row>
<EmpId>1</EmpId>
<EmpName>John</EmpName>
<DeptName>Finance</DeptName>
</row>
<row>
<EmpId>2</EmpId>
<EmpName>Peter</EmpName>
<DeptName>Admin</DeptName>
</row>
</dataset>
Run Code Online (Sandbox Code Playgroud)
我在XSLT下方编写了所需的转换:
<?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="/">
<dataset>
<xsl:for-each select="./dataset/data/rows/row">
<row>
<xsl:for-each select="/dataset/metadata/item">
<xsl:element name="{@Name}">
<xsl:for-each select="/dataset/data/rows/row/value">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:element>
</xsl:for-each>
</row>
</xsl:for-each>
</dataset>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
我得到以下输出:
<?xml version="1.0" encoding="UTF-16"?>
<dataset>
<row>
<EmpId>1JohnFinance2PeterAdmin</EmpId>
<EmpName>1JohnFinance2PeterAdmin</EmpName>
<DeptName>1JohnFinance2PeterAdmin</DeptName>
</row>
<row>
<EmpId>1JohnFinance2PeterAdmin</EmpId>
<EmpName>1JohnFinance2PeterAdmin</EmpName>
<DeptName>1JohnFinance2PeterAdmin</DeptName>
</row>
Run Code Online (Sandbox Code Playgroud)
请告诉我,我要去哪里了。
任何帮助将不胜感激。
提前致谢。
问候
这个简短的转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vNames" select="/*/metadata/*/@Name"/>
<xsl:template match="/*/data">
<dataset><xsl:apply-templates/></dataset>
</xsl:template>
<xsl:template match="row">
<row><xsl:apply-templates/></row>
</xsl:template>
<xsl:template match="row/*">
<xsl:variable name="vPos" select="position()"/>
<xsl:element name="{$vNames[$vPos]}"><xsl:apply-templates/></xsl:element>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
当应用于提供的XML文档时(添加了缺少的结束标记以使其格式正确):
<dataset>
<metadata>
<item Name="EmpId" />
<item Name="EmpName" />
<item Name="DeptName" />
</metadata>
<data>
<rows>
<row>
<value>1</value>
<value>John</value>
<value>Finance</value>
</row>
<row>
<value>2</value>
<value>Peter</value>
<value>Admin</value>
</row>
</rows>
</data>
</dataset>
Run Code Online (Sandbox Code Playgroud)
产生想要的正确结果:
<dataset>
<row>
<EmpId>1</EmpId>
<EmpName>John</EmpName>
<DeptName>Finance</DeptName>
</row>
<row>
<EmpId>2</EmpId>
<EmpName>Peter</EmpName>
<DeptName>Admin</DeptName>
</row>
</dataset>
Run Code Online (Sandbox Code Playgroud)
说明:
使用模板和XSLT模板选择机制来完成这项工作。作为XSLT通常我们宁愿xsl:apply-templates
到xsl:for-each
-从而获得更简单,更具扩展性,更易于理解和维护的代码。这是几乎100%的“推送样式”解决方案的示例。
使用xsl:variable
得到(一劳永逸)的节点,我们将与不断努力。
保存position()
变量以供以后在其他上下文中使用- position()
取决于上下文。