我想根据一个值将特定的XML节点组合在一起,并在一行中最多显示两个元素。
我已经尝试了很多,但找不到合理的工作原理。
首先,这是一个示例XML:
<apples>
<gala>
<pattern></pattern>
<mutated>self</mutated>
<marketed>Gala</marketed>
</gala>
<gala>
<pattern>stripe</pattern>
<mutated>Gala</mutated>
<marketed>Royal Gala</marketed>
</gala>
<gala>
<pattern>stripe</pattern>
<mutated>Tenroy</mutated>
<marketed>Obrogala</marketed>
</gala>
<gala>
<pattern>stripe</pattern>
<mutated>Tenroy</mutated>
<marketed>Waliser Gala</marketed>
</gala>
<gala>
<pattern>stripe</pattern>
<mutated>Tenroy</mutated>
<marketed>Caitlin</marketed>
</gala>
<gala>
<pattern>stripe</pattern>
<mutated>Imperial</mutated>
<marketed>Banning Gala</marketed>
</gala>
<gala>
<pattern>stripe</pattern>
<mutated>Tenroy</mutated>
<marketed>Smith gala</marketed>
</gala>
</apples>
我想通过突变对苹果进行分组,但前提是它们有一个模式。输出应如下:
Mutated from: Gala
Marketed as Royal Gala
Mutated from Tenroy
Marketed as Obrogala :: Marketed as Waliser Gala
Marketed as Caitlin :: Marketed as Smith Gala
Mutated from Imperial
Marketed as Banning Gala
此外,更简单的解决方案可能不是将“Marketed as Smith Gala”添加到“Tenroy”组中,而是在“Imperial”组下面创建一个新组“Tenroy”。
这是我到目前为止所尝试的内容:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="apples">
<html>
<body>
<h2>Gala Apples</h2>
<xsl:for-each select="gala[normalize-space(pattern)][position() mod 2=1]">
<!-- Add a headline for each mutation -->
<xsl:if test="preceding-sibling::gala[normalize-space(pattern)][1]/mutated != mutated or position() = 1">
<table border="1">
<tr bgcolor="#9acd32">
<th>
Mutated from: <xsl:value-of select="mutated" />
</th>
</tr>
</table>
</xsl:if>
<!-- Build a 2 column Layout for each Gala Apple -->
<table border="1">
<tr>
<td width="50%">
Marketd as: <xsl:value-of select="marketed" />
</td>
<td width="50%">
<xsl:for-each select="following-sibling::gala[normalize-space(pattern)][1]">
Marketd as: <xsl:value-of select="marketed" />
</xsl:for-each>
</td>
</tr>
</table>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
我的代码问题是,我在检查突变时只通过第一个节点(mod 2 = 1)进行迭代。如果每个组中都有偶数个苹果,这将正常工作。如果没有,它将最终陷入混乱。
我还试图计算先前兄弟突变的数量,但它也没有按预期工作。
非常感谢帮助!
答案 0 :(得分:1)
如果您的处理器支持它,您可以使用EXSLT set:distinct()函数通过变异对记录进行分组,例如:
<xsl:variable name="groups" select="set:distinct(/apples/gala/mutated)[.!='self']" />
而不是使用(更复杂的)Muenchian方法。然后,您可以使用键来获取每个组中的苹果并进行处理。恕我直言,该组应作为列表输出,并由CSS处理两列显示 - 但如果您更喜欢通过表格单元格来处理它,请尝试类似:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets">
<xsl:variable name="groups" select="set:distinct(/apples/gala/mutated)[.!='self']" />
<xsl:key name="samegGroup" match="gala" use="mutated" />
<xsl:template match="/">
<html>
<body>
<h2>Gala Apples</h2>
<table border="1" >
<xsl:for-each select="$groups">
<tr><th colspan="2"><xsl:value-of select="." /></th></tr>
<xsl:call-template name="proc">
<xsl:with-param name="group" select="key('samegGroup', .)"/>
</xsl:call-template>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
<xsl:template name="proc">
<xsl:param name="group" />
<xsl:param name="i" select="1"/>
<xsl:choose>
<xsl:when test="$i > count($group)"/>
<xsl:otherwise>
<tr>
<td>
<xsl:text>Marketed as: </xsl:text>
<xsl:value-of select="$group[$i]/marketed" />
</td>
<td>
<xsl:if test="$i < count($group)">
<xsl:text>Marketed as: </xsl:text>
<xsl:value-of select="$group[$i+1]/marketed" />
</xsl:if>
</td>
</tr>
<xsl:call-template name="proc">
<xsl:with-param name="group" select="$group"/>
<xsl:with-param name="i" select="$i+2"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>