我有一个有趣的XSL场景由你们运行。到目前为止,我的解决方案似乎效率低下(转换时间显着增加),所以我想把它放在那里。
方案 从以下XML中我们需要获取每个类别的最新新闻的ID。
XML 在XML中,我有一个新闻项列表,一个新闻类别列表和一个项目类别关系列表。项目列表和项目类别列表也可以是随机顺序(不是按日期排序)。
<news>
<itemlist>
<item id="1">
<attribute name="title">Great new products</attribute>
<attribute name="startdate">2009-06-13T00:00:00</attribute>
</item>
<item id="2">
<attribute name="title">FTSE down</attribute>
<attribute name="startdate">2009-10-01T00:00:00</attribute>
</item>
<item id="3">
<attribute name="title">SAAB go under</attribute>
<attribute name="startdate">2008-01-22T00:00:00</attribute>
</item>
<item id="4">
<attribute name="title">M&A on increase</attribute>
<attribute name="startdate">2010-05-11T00:00:00</attribute>
</item>
</itemlist>
<categorylist>
<category id="1">
<name>Finance</name>
</category>
<category id="2">
<name>Environment</name>
</category>
<category id="3">
<name>Health</name>
</category>
</categorylist>
<itemcategorylist>
<itemcategory itemid="1" categoryid="2" />
<itemcategory itemid="2" categoryid="3" />
<itemcategory itemid="3" categoryid="1" />
<itemcategory itemid="4" categoryid="1" />
<itemcategory itemid="4" categoryid="2" />
<itemcategory itemid="2" categoryid="2" />
</itemcategorylist>
</news>
我尝试了什么 使用rtf
<xsl:template match="/">
<!-- for each category -->
<xsl:for-each select="/news/categorylist/category">
<xsl:variable name="categoryid" select="@id"/>
<!-- create RTF item list containing only items in that list ordered by startdate -->
<xsl:variable name="ordereditemlist">
<xsl:for-each select="/news/itemlist/item">
<xsl:sort select="attribute[@name='startdate']" order="descending" data-type="text"/>
<xsl:variable name="itemid" select="@id" />
<xsl:if test="/news/itemcategorylist/itemcategory[@categoryid = $categoryid][@itemid=$itemid]">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<!-- get the id of the first item in the list -->
<xsl:variable name="firstitemid" select="msxsl:node-set($ordereditemlist)/item[position()=1]/@id"/>
</xsl:for-each>
</xsl:template>
非常感谢您的任何想法。
谢谢, 亚历
答案 0 :(得分:5)
我将如何做到这一点:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output encoding="utf-8" />
<!-- this is (literally) the key to the solution -->
<xsl:key name="kItemByItemCategory" match="item" use="
/news/itemcategorylist/itemcategory[@itemid = current()/@id]/@categoryid
" />
<xsl:template match="/news">
<latest>
<xsl:apply-templates select="categorylist/category" mode="latest" />
</latest>
</xsl:template>
<xsl:template match="category" mode="latest">
<xsl:variable name="self" select="." />
<!-- sorted loop to get the latest news item -->
<xsl:for-each select="key('kItemByItemCategory', @id)">
<xsl:sort select="attribute[@name='startdate']" order="descending" />
<xsl:if test="position() = 1">
<category name="{$self/name}">
<xsl:apply-templates select="." />
</category>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="item">
<!-- for the sake of the example, just copy the node -->
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>
<xsl:key>
按关联的类别ID为每个新闻项编制索引。现在,您可以通过一种简单的方法检索属于某个类别的所有新闻项。剩下的就是直截了当。
为我输出:
<latest>
<category name="Finance">
<item id="4">
<attribute name="title">M&A on increase</attribute>
<attribute name="startdate">2010-05-11T00:00:00</attribute>
</item>
</category>
<category name="Environment">
<item id="4">
<attribute name="title">M&A on increase</attribute>
<attribute name="startdate">2010-05-11T00:00:00</attribute>
</item>
</category>
<category name="Health">
<item id="2">
<attribute name="title">FTSE down</attribute>
<attribute name="startdate">2009-10-01T00:00:00</attribute>
</item>
</category>
</latest>
答案 1 :(得分:2)
看起来你应该探索<xsl:key>
。这有效地创建了一个hashmap并避免了所有内容的循环。
更新以下是典型的教程:
答案 2 :(得分:1)
你们循环浏览所有项目并按日期对它们进行排序,然后由于不属于正确的类别而将大部分项目扔掉。
也许这样的事情可能更适合你的情况:
<xsl:variable name="ordereditemlist">
<xsl:for-each select="/news/itemcategorylist/itemcategory[@categoryid = $categoryid]">
<xsl:variable name="itemid" select="@itemid"/>
继续从那里收集您实际需要的新闻项目,然后对它们进行排序和复制。