XSLT 将结果分成 3 组 [英] XSLT split result in groups of 3
问题描述
一个网络应用程序为我提供了一个 XML 提要,我无法更改.我想要做的是将这个 XML-feed 拆分成几个无序列表.我正在尝试使用下面的 XSLT 来做到这一点.
An web-application is providing me an XML-feed, which I can't change. What I want to do is split this XML-feed into several unordered lists. I'm trying to do this with the XSLT below.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" encoding="utf-8" />
<xsl:param name="html-content-type" />
<xsl:template match="/NavigationTree">
<xsl:if test="count(//Page) > 0">
<ul>
<xsl:apply-templates select="Page">
</xsl:apply-templates>
</ul>
</xsl:if>
</xsl:template>
<xsl:template match="//Page">
<li class="{position() mod 3}">
<xsl:text disable-output-escaping="yes"><![CDATA[» ]]></xsl:text>
<a>
<xsl:attribute name="href">
<xsl:value-of select="@FriendlyHref" disable-output-escaping="yes"/>
</xsl:attribute>
<xsl:value-of select="@MenuText" disable-output-escaping="no"/>
</a>
</li>
<xsl:if test="position() mod 3 = 0">
<xsl:if test="position() < count(//Page)">
<!--Don't know if this is the correct approach, but when the position is 3 and there are more items following
I want to create an new unordered list-->
</xsl:if>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
使用上面的 XSLT,我可以将 XML 转换为一个包含 6 个项目的无序列表(假设总是有 6 个项目).类似于下面的例子;
Using the XSLT above i'm able to turn the XML into an unordered list with 6 items in it (let's assume there always are 6 items). Similar to the example below;
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
<li>Item4</li>
<li>Item5</li>
<li>Item6</li>
</ul>
上面的例子是我目前得到的结果.但是想要的结果是这样的;
The example above is the result i'm getting at the moment. But the desired result is something like this;
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
<ul>
<li>Item4</li>
<li>Item5</li>
<li>Item6</li>
</ul>
编辑 - 示例 XML 输入
EDIT - Sample XML input
<NavigationTree>
<Settings>
<!--Snipped data-->
</Settings>
<Page ID="5" AreaID="1" MenuText="Bestellen" MouseOver="" Href="Default.aspx?ID=5" FriendlyHref="/nl-nl/klantenservice/bestellen.aspx" Image="" ImageActive="" ImageMouseOver="" Title="" Allowclick="True" ShowInSitemap="True" ShowInLegend="True" AbsoluteLevel="2" RelativeLevel="2" Sort="1" LastInLevel="False" InPath="False" ChildCount="0" class="L2" Active="False" IsPagePasswordProtected="False" IsPageUserProtected="False" CanAccessPasswordProtectedPage="False" CanAccessUserProtectedPage="True"/>
<Page ID="6" AreaID="1" MenuText="Betalen" MouseOver="" Href="Default.aspx?ID=6" FriendlyHref="/nl-nl/klantenservice/betalen.aspx" Image="" ImageActive="" ImageMouseOver="" Title="" Allowclick="True" ShowInSitemap="True" ShowInLegend="True" AbsoluteLevel="2" RelativeLevel="2" Sort="2" LastInLevel="False" InPath="True" ChildCount="0" class="L2_Active" Active="True" IsPagePasswordProtected="False" IsPageUserProtected="False" CanAccessPasswordProtectedPage="False" CanAccessUserProtectedPage="True"/>
<Page ID="7" AreaID="1" MenuText="Retourneren" MouseOver="" Href="Default.aspx?ID=7" FriendlyHref="/nl-nl/klantenservice/retourneren.aspx" Image="" ImageActive="" ImageMouseOver="" Title="" Allowclick="True" ShowInSitemap="True" ShowInLegend="True" AbsoluteLevel="2" RelativeLevel="2" Sort="3" LastInLevel="False" InPath="False" ChildCount="0" class="L2" Active="False" IsPagePasswordProtected="False" IsPageUserProtected="False" CanAccessPasswordProtectedPage="False" CanAccessUserProtectedPage="True"/>
<Page ID="8" AreaID="1" MenuText="Garantie" MouseOver="" Href="Default.aspx?ID=8" FriendlyHref="/nl-nl/klantenservice/garantie.aspx" Image="" ImageActive="" ImageMouseOver="" Title="" Allowclick="True" ShowInSitemap="True" ShowInLegend="True" AbsoluteLevel="2" RelativeLevel="2" Sort="4" LastInLevel="False" InPath="False" ChildCount="0" class="L2" Active="False" IsPagePasswordProtected="False" IsPageUserProtected="False" CanAccessPasswordProtectedPage="False" CanAccessUserProtectedPage="True"/>
<Page ID="9" AreaID="1" MenuText="Faq" MouseOver="" Href="Default.aspx?ID=9" FriendlyHref="/nl-nl/klantenservice/veel-gestelde-vragen.aspx" Image="" ImageActive="" ImageMouseOver="" Title="" Allowclick="True" ShowInSitemap="True" ShowInLegend="True" AbsoluteLevel="2" RelativeLevel="2" Sort="5" LastInLevel="False" InPath="False" ChildCount="0" class="L2" Active="False" IsPagePasswordProtected="False" IsPageUserProtected="False" CanAccessPasswordProtectedPage="False" CanAccessUserProtectedPage="True"/>
<Page ID="10" AreaID="1" MenuText="Contact" MouseOver="" Href="Default.aspx?ID=10" FriendlyHref="/nl-nl/klantenservice/contact.aspx" Image="" ImageActive="" ImageMouseOver="" Title="" Allowclick="True" ShowInSitemap="True" ShowInLegend="True" AbsoluteLevel="2" RelativeLevel="2" Sort="6" LastInLevel="True" InPath="False" ChildCount="0" class="L2" Active="False" IsPagePasswordProtected="False" IsPageUserProtected="False" CanAccessPasswordProtectedPage="False" CanAccessUserProtectedPage="True"/>
</NavigationTree>
如您所见,我总是希望以 3 个项目为一组进行输出.是否可以使用 XSLT 进行这种 html 输出?如果是,我该怎么做?欢迎任何帮助!
As you can see I always want output in groups of 3 items. Is this kind of html output possible using XSLT? If yes, how can I do this? Any help is welcome!
推荐答案
为此,您需要在 Page 元素上匹配它的位置 1、4、7 等...换句话说,position() mod 3 等于 1.
To do this, you need to match on the Page element that it is position 1, 4, 7, etc... In other words, where there position() mod 3 equals 1.
<xsl:if test="position() mod 3 = 1">
这给出了列表的第一个元素.然后你可以得到 this 中剩余的 2 个元素,就像这样
This gives the first element of the list. You can then get the remaining 2 elements in the this, like so
<xsl:apply-templates select=".|following-sibling::Page[position() < 3]" mode="list"/>
综上所述,给出以下 XSLT
Putting this altogether, gives the following XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes" encoding="utf-8"/>
<xsl:param name="html-content-type"/>
<xsl:param name="group-size" select="3"/>
<xsl:template match="/NavigationTree">
<xsl:if test="count(//Page) > 0">
<xsl:apply-templates select="Page"/>
</xsl:if>
</xsl:template>
<xsl:template match="Page">
<xsl:if test="position() mod $group-size = 1">
<ul>
<xsl:apply-templates select=".|following-sibling::Page[position() < $group-size]" mode="list"/>
</ul>
</xsl:if>
</xsl:template>
<xsl:template match="Page" mode="list">
<li class="{position()}">
<xsl:text disable-output-escaping="yes"><![CDATA[» ]]></xsl:text>
<a>
<xsl:attribute name="href">
<xsl:value-of select="@FriendlyHref" disable-output-escaping="yes"/>
</xsl:attribute>
<xsl:value-of select="@MenuText" disable-output-escaping="no"/>
</a>
</li>
</xsl:template>
</xsl:stylesheet>
在您的输入 XML 上运行时,这应该生成以下输出
When run on your input XML, this should generate the following output
<ul>
<li class="1">» <a href="/nl-nl/klantenservice/bestellen.aspx">Bestellen</a></li>
<li class="2">» <a href="/nl-nl/klantenservice/betalen.aspx">Betalen</a></li>
<li class="3">» <a href="/nl-nl/klantenservice/retourneren.aspx">Retourneren</a></li>
</ul>
<ul>
<li class="1">» <a href="/nl-nl/klantenservice/garantie.aspx">Garantie</a></li>
<li class="2">» <a href="/nl-nl/klantenservice/veel-gestelde-vragen.aspx">Faq</a></li>
<li class="3">» <a href="/nl-nl/klantenservice/contact.aspx">Contact</a></li>
</ul>
请注意,我已经参数化了组大小,例如,允许您轻松更改为每个列表 4 或 5 个元素.
Do note I have parameterised the group size, allowing you to easily change to 4 or 5 elements per list, for example.
这篇关于XSLT 将结果分成 3 组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!