Xml 使用XSLT进行多级条件打印
本周早些时候,我问了一个关于使用XSLT进行条件打印的问题,并从helderdarocha那里得到了一个非常有用的答案。不幸的是,事实证明我需要的答案比我最初想象的要复杂一些。按照他的指示,并使用Muenchian方法进行控制中断,我总结了一个我需要做的新示例 以下是我的XML:Xml 使用XSLT进行多级条件打印,xml,xslt,formatting,grouping,Xml,Xslt,Formatting,Grouping,本周早些时候,我问了一个关于使用XSLT进行条件打印的问题,并从helderdarocha那里得到了一个非常有用的答案。不幸的是,事实证明我需要的答案比我最初想象的要复杂一些。按照他的指示,并使用Muenchian方法进行控制中断,我总结了一个我需要做的新示例 以下是我的XML: <?xml version="1.0" encoding="UTF-8"?> <group> <person> <
<?xml version="1.0" encoding="UTF-8"?>
<group>
<person>
<datum type='medium'>Cartoon</datum>
<datum type='firstname'>Fred</datum>
<datum type='lastname'>Flintstone</datum>
</person>
<person>
<datum type='medium'>Cartoon</datum>
<datum type='firstname'>Wilma</datum>
<datum type='lastname'>Flintstone</datum>
</person>
<person>
<datum type='medium'>TV</datum>
<datum type='firstname'>Luke</datum>
<datum type='lastname'>Duke</datum>
</person>
<person>
<datum type='medium'>TV</datum>
<datum type='firstname'>Daisy</datum>
<datum type='lastname'>Duke</datum>
</person>
<person>
<datum type='medium'>Reality</datum>
<datum type='firstname'>George</datum>
<datum type='lastname'>Bush</datum>
</person>
<person>
<datum type='medium'>Reality</datum>
<datum type='firstname'>Barbara</datum>
<datum type='lastname'>Bush</datum>
</person>
</group>
卡通
弗莱德
燧石
卡通
威尔玛
燧石
电视
卢克
公爵
电视
雏菊
公爵
现实
乔治
灌木丛
现实
芭芭拉
灌木丛
这是我的XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:key name="medium" match="person" use="datum[@type='medium']"/>
<xsl:key name="lastname" match="person" use="//person/datum[@type='lastname']"/>
<xsl:template match="person">
<tr>
<td><xsl:value-of select="datum[@type='firstname']"/></td>
</tr>
</xsl:template>
<xsl:template match="group">
<table border="1">
<xsl:for-each select="person[count(. | key('medium', datum[@type='medium'])[1]) = 1]/datum[@type='medium']">
<xsl:sort/>
<tr bgcolor="#cccccc">
<td><xsl:value-of select="."/></td>
</tr>
<xsl:for-each select="//person[count(. | key('lastname', //person/datum[@type='lastname'])[1]) = 1]/datum[@type='lastname']">
<xsl:sort/>
<tr bgcolor="#ccffcc">
<td><xsl:value-of select="."/></td>
</tr>
<xsl:apply-templates select="//person[datum[@type='lastname'] = current()]">
<xsl:sort select="datum[@type='firstname']"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
这是我的输出:
但这就是我正在尝试的:
我假设我的问题是这一行:
我相信我没有正确格式化xpath,但不幸的是,我对xpath的理解仍然相对薄弱。。。我的假设是,我需要将“=1”检查移动到其他地方,但不确定如何执行此操作
一如既往,任何和所有线索都会受到赞赏。您已经正确地开始定义“媒介”的键 我在这里使用的是generate id方法,但是您可以像以前一样使用count方法。注意这里“mode”的用法。因为我使用的是xsl:apply-templates,所以最终会有多个模板匹配person元素,因此模式会区分它们 使用此“medium”模板,您将获得不同的“lastname”条目,但使用类似的连接键(应用于当前组中由“medium”键访问的所有元素):
最后,在“lastname”模板中,您将再次使用连接键获取组中的所有person元素:
<xsl:apply-templates
select="key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))" />
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:key name="medium" match="person" use="datum[@type='medium']" />
<xsl:key name="medium-lastname" match="person" use="concat(datum[@type='medium'], '|', datum[@type='lastname'])" />
<xsl:template match="group">
<table>
<xsl:apply-templates select="person[generate-id() = generate-id(key('medium', datum[@type='medium'])[1])]" mode="medium" />
</table>
</xsl:template>
<xsl:template match="person" mode="medium">
<tr class="medium">
<td><xsl:value-of select="datum[@type='medium']" /></td>
</tr>
<xsl:apply-templates select="key('medium', datum[@type='medium'])[generate-id() = generate-id(key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))[1])]" mode="lastname" />
</xsl:template>
<xsl:template match="person" mode="lastname">
<tr class="lastname">
<td><xsl:value-of select="datum[@type='lastname']" /></td>
</tr>
<xsl:apply-templates select="key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))" />
</xsl:template>
<xsl:template match="person">
<tr>
<td><xsl:value-of select="datum[@type='firstname']" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>
当应用于此XML时
<group>
<person>
<datum type="medium">Cartoon</datum>
<datum type="firstname">Fred</datum>
<datum type="lastname">Flintstone</datum>
</person>
<person>
<datum type="medium">Cartoon</datum>
<datum type="firstname">Wilma</datum>
<datum type="lastname">Flintstone</datum>
</person>
<person>
<datum type="medium">Cartoon</datum>
<datum type="firstname">Barney</datum>
<datum type="lastname">Rubble</datum>
</person>
<person>
<datum type="medium">TV</datum>
<datum type="firstname">Daisy</datum>
<datum type="lastname">Duke</datum>
</person>
<person>
<datum type="medium">TV</datum>
<datum type="firstname">George</datum>
<datum type="lastname">Bush</datum>
</person>
</group>
卡通
弗莱德
燧石
卡通
威尔玛
燧石
卡通
巴尼
瓦砾
电视
雏菊
公爵
电视
乔治
灌木丛
然后输出以下内容
<table>
<tr class="medium">
<td>Cartoon</td>
</tr>
<tr class="lastname">
<td>Flintstone</td>
</tr>
<tr>
<td>Fred</td>
</tr>
<tr>
<td>Wilma</td>
</tr>
<tr class="lastname">
<td>Rubble</td>
</tr>
<tr>
<td>Barney</td>
</tr>
<tr class="medium">
<td>TV</td>
</tr>
<tr class="lastname">
<td>Duke</td>
</tr>
<tr>
<td>Daisy</td>
</tr>
<tr class="lastname">
<td>Bush</td>
</tr>
<tr>
<td>George</td>
</tr>
</table>
卡通
燧石
弗莱德
威尔玛
瓦砾
巴尼
电视
公爵
雏菊
灌木丛
乔治
通过为“介质”定义一个键,您已经正确地开始了
我在这里使用的是generate id方法,但是您可以像以前一样使用count方法。注意这里“mode”的用法。因为我使用的是xsl:apply-templates,所以最终会有多个模板匹配person元素,因此模式会区分它们
使用此“medium”模板,您将获得不同的“lastname”条目,但使用类似的连接键(应用于当前组中由“medium”键访问的所有元素):
最后,在“lastname”模板中,您将再次使用连接键获取组中的所有person元素:
<xsl:apply-templates
select="key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))" />
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:key name="medium" match="person" use="datum[@type='medium']" />
<xsl:key name="medium-lastname" match="person" use="concat(datum[@type='medium'], '|', datum[@type='lastname'])" />
<xsl:template match="group">
<table>
<xsl:apply-templates select="person[generate-id() = generate-id(key('medium', datum[@type='medium'])[1])]" mode="medium" />
</table>
</xsl:template>
<xsl:template match="person" mode="medium">
<tr class="medium">
<td><xsl:value-of select="datum[@type='medium']" /></td>
</tr>
<xsl:apply-templates select="key('medium', datum[@type='medium'])[generate-id() = generate-id(key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))[1])]" mode="lastname" />
</xsl:template>
<xsl:template match="person" mode="lastname">
<tr class="lastname">
<td><xsl:value-of select="datum[@type='lastname']" /></td>
</tr>
<xsl:apply-templates select="key('medium-lastname', concat(datum[@type='medium'], '|', datum[@type='lastname']))" />
</xsl:template>
<xsl:template match="person">
<tr>
<td><xsl:value-of select="datum[@type='firstname']" /></td>
</tr>
</xsl:template>
</xsl:stylesheet>
当应用于此XML时
<group>
<person>
<datum type="medium">Cartoon</datum>
<datum type="firstname">Fred</datum>
<datum type="lastname">Flintstone</datum>
</person>
<person>
<datum type="medium">Cartoon</datum>
<datum type="firstname">Wilma</datum>
<datum type="lastname">Flintstone</datum>
</person>
<person>
<datum type="medium">Cartoon</datum>
<datum type="firstname">Barney</datum>
<datum type="lastname">Rubble</datum>
</person>
<person>
<datum type="medium">TV</datum>
<datum type="firstname">Daisy</datum>
<datum type="lastname">Duke</datum>
</person>
<person>
<datum type="medium">TV</datum>
<datum type="firstname">George</datum>
<datum type="lastname">Bush</datum>
</person>
</group>
卡通
弗莱德
燧石
卡通
威尔玛
燧石
卡通
巴尼
瓦砾
电视
雏菊
公爵
电视
乔治
灌木丛
然后输出以下内容
<table>
<tr class="medium">
<td>Cartoon</td>
</tr>
<tr class="lastname">
<td>Flintstone</td>
</tr>
<tr>
<td>Fred</td>
</tr>
<tr>
<td>Wilma</td>
</tr>
<tr class="lastname">
<td>Rubble</td>
</tr>
<tr>
<td>Barney</td>
</tr>
<tr class="medium">
<td>TV</td>
</tr>
<tr class="lastname">
<td>Duke</td>
</tr>
<tr>
<td>Daisy</td>
</tr>
<tr class="lastname">
<td>Bush</td>
</tr>
<tr>
<td>George</td>
</tr>
</table>
卡通
燧石
弗莱德
威尔玛
瓦砾
巴尼
电视
公爵
雏菊
灌木丛
乔治
这里的关键是使用
按介质分组,然后按姓氏分组。以下这些应该是有效的。您可以看到它在这里工作:
这里的关键是使用
按介质分组,然后按姓氏分组。以下这些应该是有效的。您可以看到它在这里工作:
请不要发布代码和数据的截图。把实际的代码和数据放在你的文章中,格式化为代码。当我这样做时,它会告诉我代码格式不正确,然后不让我发布。相信我,我更愿意这样做。将代码粘贴到文本编辑器中,将所有制表符转换为4个空格,将所有内容缩进4个空格,然后粘贴到SO编辑窗口中,在代码上下各有一个空行。如果你真的,真的无法用代码编辑文章,请转到,
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<table border="1">
<xsl:for-each-group select="/group/person" group-by="datum[@type='medium']">
<tr bgcolor="#cccccc"><td><xsl:value-of select="current-grouping-key()"/></td></tr>
<xsl:for-each-group select="current-group()" group-by="datum[@type='lastname']">
<tr bgcolor="#ccffcc"><td><xsl:value-of select="current-grouping-key()"/></td></tr>
<xsl:for-each select="current-group()">
<tr><td><xsl:value-of select="./datum[@type='firstname']"/></td></tr>
</xsl:for-each>
</xsl:for-each-group>
</xsl:for-each-group>
</table>
</xsl:template>
</xsl:transform>