我想知道是否有一种方法可以同时迭代XML文档和两组节点,我知道这不是一个非常具有描述性的问题,所以这里有一个例子:
xml示例:
<document>
<animal species="dog">
<fact>4 legs</fact>
<fact>2 eyes</fact>
<fact>loyal</fact>
</animal>
<animal species="horse">
<fact>rideable</fact>
<fact>4 legs</fact>
<fact>2 eyes</fact>
<fact>huge</fact>
</animal>
</document>
xsl需要编辑:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Results</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Dogs</th>
<th>Horses</th>
</tr>
<xsl:for-each select="document">
<???for all greater quantity of facts between the 2 in this document>
<tr>
<td><xsl:value-of select="./animal/@dog/fact[current#]"/></td>
<td><xsl:value-of select="./animal/@horse/fact[current#]"/></td>
</tr>
</???>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
究竟应该更换???用于检索以下表格的方法?
Dogs |Horses |
4 legs |rideable |
2 eyes |4 legs |
loyal |2 eyes |
感谢任何可能的帮助。
答案 0 :(得分:0)
像往常一样,如果你被困在XSLT1并且不能使用xsl:for-each-group,你想使用muenchian分组
<html>
<body>
<h2>Results</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Dogs</th>
<th>Horses</th>
</tr>
<tr>
<td>4 legs</td>
<td>rideable</td>
</tr>
<tr>
<td>2 eyes</td>
<td>4 legs</td>
</tr>
<tr>
<td>loyal</td>
<td>2 eyes</td>
</tr>
<tr>
<td></td>
<td>huge</td>
</tr>
</table>
</body>
</html>
来自这个xslt
- <xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Results</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Dogs</th>
<th>Horses</th>
</tr>
<xsl:for-each select="document">
<xsl:for-each select="animal/fact[generate-id()=generate-id(key('f',1+count(preceding-sibling::fact))[1])]">
<tr>
<xsl:variable name="k" select="key('f',1+count(preceding-sibling::fact))"/>
<td><xsl:value-of select="$k[../@species='dog']"/></td>
<td><xsl:value-of select="$k[../@species='horse']"/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
<xsl:key name="f" match="fact" use="1+count(preceding-sibling::fact)"/>
</xsl:stylesheet>
答案 1 :(得分:0)
我的解决方案适用于XSLT 1.0,并在Altova XMLSpy下工作。以下模板:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>Results</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Dogs</th>
<th>Horses</th>
</tr>
<xsl:apply-templates select="document">
<xsl:with-param name="num" select="1" />
</xsl:apply-templates>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="document">
<xsl:param name="num" />
<xsl:if test="count(animal/fact[$num]) = count(animal)">
<tr>
<xsl:for-each select="animal">
<td><xsl:value-of select="fact[$num]"/></td>
</xsl:for-each>
</tr>
<xsl:apply-templates select=".">
<xsl:with-param name="num" select="$num + 1"/>
</xsl:apply-templates>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
应用于提供的输入XML,给出以下结果:
<html>
<body>
<h2>Results</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Dogs</th>
<th>Horses</th>
</tr>
<tr>
<td>4 legs</td>
<td>rideable</td>
</tr>
<tr>
<td>2 eyes</td>
<td>4 legs</td>
</tr>
<tr>
<td>loyal</td>
<td>2 eyes</td>
</tr>
</table>
</body>
</html>
我认为你不想生成只填充一个单元格的行(不应该考虑huge
列中只有Horse
值的最后一行。这与David的解决方案不同。
编辑:但是,改变我的方法以获得与David相同的结果非常简单。它只需要通过调用count()
XPATH函数来改变条件:
<xsl:if test="count(animal/fact[$num]) > 0">
而不是:
<xsl:if test="count(animal/fact[$num]) = count(animal)">
完成后,您将获得以下输出:
<html>
<body>
<h2>Results</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Dogs</th>
<th>Horses</th>
</tr>
<tr>
<td>4 legs</td>
<td>rideable</td>
</tr>
<tr>
<td>2 eyes</td>
<td>4 legs</td>
</tr>
<tr>
<td>loyal</td>
<td>2 eyes</td>
</tr>
<tr>
<td></td>
<td>huge</td>
</tr>
</table>
</body>
</html>
答案 2 :(得分:0)
这是一个通用的XSLT 1.0解决方案,可以在XML文档中存在任何数量的动物时正常工作。没有物种名称是硬编码的:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vHavingMaxFactsPosition">
<xsl:for-each select="/*/animal">
<xsl:sort select="count(*)" data-type="number"
order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="count(preceding-sibling::animal)+1"/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="vHavingMaxFacts" select=
"/*/*[position() = $vHavingMaxFactsPosition]"/>
<xsl:template match="/*">
<html>
<body>
<table border="1">
<tr>
<xsl:apply-templates select="*/@species"/>
</tr>
<xsl:apply-templates mode="startRow" select="$vHavingMaxFacts/*"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="fact" mode="startRow">
<xsl:variable name="vPos" select="position()"/>
<tr>
<xsl:for-each select="/*/*">
<td><xsl:value-of select="*[position()=$vPos]"/></td>
</xsl:for-each>
</tr>
</xsl:template>
<xsl:template match="@species">
<th><xsl:value-of select="."/></th>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档:
<document>
<animal species="dog">
<fact>4 legs</fact>
<fact>2 eyes</fact>
<fact>loyal</fact>
</animal>
<animal species="horse">
<fact>rideable</fact>
<fact>4 legs</fact>
<fact>2 eyes</fact>
<fact>huge</fact>
</animal>
</document>
产生了想要的正确结果:
<html>
<body>
<table border="1">
<tr>
<th>dog</th>
<th>horse</th>
</tr>
<tr>
<td>4 legs</td>
<td>rideable</td>
</tr>
<tr>
<td>2 eyes</td>
<td>4 legs</td>
</tr>
<tr>
<td>loyal</td>
<td>2 eyes</td>
</tr>
<tr>
<td></td>
<td>huge</td>
</tr>
</table>
</body>
</html>
当上面对此XML文档应用相同的转换时(3个动物 - 添加了5个事实的蜘蛛):
<document>
<animal species="dog">
<fact>4 legs</fact>
<fact>2 eyes</fact>
<fact>loyal</fact>
</animal>
<animal species="horse">
<fact>rideable</fact>
<fact>4 legs</fact>
<fact>2 eyes</fact>
<fact>huge</fact>
</animal>
<animal species="spider">
<fact>insect</fact>
<fact>6 legs</fact>
<fact>x eyes</fact>
<fact>small</fact>
<fact>dangerous</fact>
</animal>
</document>
再次生成正确的结果:
<html>
<body>
<table border="1">
<tr>
<th>dog</th>
<th>horse</th>
<th>spider</th>
</tr>
<tr>
<td>4 legs</td>
<td>rideable</td>
<td>insect</td>
</tr>
<tr>
<td>2 eyes</td>
<td>4 legs</td>
<td>6 legs</td>
</tr>
<tr>
<td>loyal</td>
<td>2 eyes</td>
<td>x eyes</td>
</tr>
<tr>
<td></td>
<td>huge</td>
<td>small</td>
</tr>
<tr>
<td></td>
<td></td>
<td>dangerous</td>
</tr>
</table>
</body>
</html>