从这个XML源:
<?xml version="1.0" encoding="utf-8" ?>
<ROOT>
<STRUCT>
<COL order="1" nodeName="FOO/BAR" colName="Foo Bar" />
<COL order="2" nodeName="FIZZ" colName="Fizz" />
</STRUCT>
<DATASET>
<DATA>
<FIZZ>testFizz</FIZZ>
<FOO>
<BAR>testBar</BAR>
<LIB>testLib</LIB>
</FOO>
</DATA>
<DATA>
<FIZZ>testFizz2</FIZZ>
<FOO>
<BAR>testBar2</BAR>
<LIB>testLib2</LIB>
</FOO>
</DATA>
</DATASET>
</ROOT>
Run Code Online (Sandbox Code Playgroud)
我想生成这个HTML:
<html>
<head>
<title>Test</title>
</head>
<body>
<table border="1">
<tr>
<td>Foo Bar</td>
<td>Fizz</td>
</tr>
<tr>
<td>testBar</td>
<td>testFizz</td>
</tr>
<tr>
<td>testBar2</td>
<td>testFizz2</td>
</tr>
</table>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
这是我目前拥有的XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/ROOT">
<html>
<head>
<title>Test</title>
</head>
<body>
<table border="1">
<tr>
<!--Generate the table header-->
<xsl:apply-templates select="STRUCT/COL">
<xsl:sort data-type="number" select="@order"/>
</xsl:apply-templates>
</tr>
<xsl:apply-templates select="DATASET/DATA" />
</table>
</body>
</html>
</xsl:template>
<xsl:template match="COL">
<!--Template for generating the table header-->
<td>
<xsl:value-of select="@colName"/>
</td>
</xsl:template>
<xsl:template match="DATA">
<xsl:variable name="pos" select="position()" />
<tr>
<xsl:for-each select="/ROOT/STRUCT/COL">
<xsl:sort data-type="number" select="@order"/>
<xsl:variable name="elementName" select="@nodeName" />
<td>
<xsl:value-of select="/ROOT/DATASET/DATA[$pos]/*[name() = $elementName]" />
</td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
它几乎可以工作,我的问题是从STRUCT块的"nodeName"属性值中指定的路径中检索正确的DATA节点.
这是一个纯XSLT 1.0解决方案,不使用任何扩展:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<html>
<head>
<title>Test</title>
</head>
<body>
<table border="1">
<xsl:apply-templates select="*/STRUCT"/>
<xsl:apply-templates select="*/DATASET/DATA"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="STRUCT">
<tr>
<xsl:apply-templates select="COL"/>
</tr>
</xsl:template>
<xsl:template match="COL">
<td><xsl:value-of select="@colName"/></td>
</xsl:template>
<xsl:template match="DATA">
<tr>
<xsl:apply-templates select="/*/STRUCT/*/@nodeName">
<xsl:with-param name="pCurrentNode" select="."/>
</xsl:apply-templates>
</tr>
</xsl:template>
<xsl:template match="@nodeName" name="getNodeValue">
<xsl:param name="pExpression" select="string(.)"/>
<xsl:param name="pCurrentNode"/>
<xsl:choose>
<xsl:when test="not(contains($pExpression, '/'))">
<td><xsl:value-of select="$pCurrentNode/*[name()=$pExpression]"/></td>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="getNodeValue">
<xsl:with-param name="pExpression"
select="substring-after($pExpression, '/')"/>
<xsl:with-param name="pCurrentNode" select=
"$pCurrentNode/*[name()=substring-before($pExpression, '/')]"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
当此转换应用于提供的XML文档时:
<ROOT>
<STRUCT>
<COL order="1" nodeName="FOO/BAR" colName="Foo Bar" />
<COL order="2" nodeName="FIZZ" colName="Fizz" />
</STRUCT>
<DATASET>
<DATA>
<FIZZ>testFizz</FIZZ>
<FOO>
<BAR>testBar</BAR>
<LIB>testLib</LIB>
</FOO>
</DATA>
<DATA>
<FIZZ>testFizz2</FIZZ>
<FOO>
<BAR>testBar2</BAR>
<LIB>testLib2</LIB>
</FOO>
</DATA>
</DATASET>
</ROOT>
Run Code Online (Sandbox Code Playgroud)
产生了想要的正确结果:
<html>
<head>
<title>Test</title>
</head>
<body>
<table border="1">
<tr>
<td>Foo Bar</td>
<td>Fizz</td>
</tr>
<tr>
<td>testBar</td>
<td>testFizz</td>
</tr>
<tr>
<td>testBar2</td>
<td>testFizz2</td>
</tr>
</table>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)