从这个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 FIZZtestFizz/FIZZ FOO BARtestBar/BAR LIBtestLib/LIB
<?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>
我想生成这个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>
这是我目前拥有的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>
它几乎可以工作,我的问题是从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>
当此转换应用于提供的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>
产生了想要的正确结果:
<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>