我编译了以下转换脚本。其目的是为每个唯一的行ID找到最高分。遗憾的是,这是通过将解决方案拼凑到类似问题而创建的,我并不完全理解该解决方案。我还试图将其纳入转换中,即按降序对返回的记录进行排序。
示例代码:
<?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" version="1.0" encoding="UTF-8" indent="yes" standalone="yes"/>
<xsl:key name="kRecordByRowID" match="record" use="CON_ROW_ID"/>
<xsl:template match="record" />
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"> <!-- Insert sort here for partially working sorting-->
<xsl:sort select="/SCORE" order="descending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="record[count(.|key('kRecordByRowID',CON_ROW_ID)[1]) = 1]">
<xsl:for-each select="key('kRecordByRowID',CON_ROW_ID)">
<xsl:if test="position()=1">
<xsl:call-template name="identity"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
示例输入:
<records>
<record>
<CON_ROW_ID>F</CON_ROW_ID>
<SCORE>80</SCORE>
</record>
<record>
<CON_ROW_ID>D</CON_ROW_ID>
<SCORE>90</SCORE>
</record>
<record>
<CON_ROW_ID>D</CON_ROW_ID>
<SCORE>75</SCORE>
</record>
<record>
<CON_ROW_ID>F</CON_ROW_ID>
<SCORE>85</SCORE>
</record>
</records>
正如您在代码中看到的那样,有一条注释说我可以将排序代码()插入到标记中,但它会返回不正确的结果。结果被分类到一个点,然后它们变得随机。
此分类代码应放在何处以正确返回分数降序列表?
答案 0 :(得分:0)
没有/SCORE
元素(sort
永远不会选择它)。您想要的是使用SCORE
中的上下文record
元素,这样就可以SCORE
。
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"> <!-- Insert sort here for partially working sorting-->
<xsl:sort select="SCORE" order="descending"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
答案 1 :(得分:0)
可悲的是,这是通过拼凑相似的解决方案来创造的 问题,我不完全理解解决方案。
为什么不以更明智的方式重写它,例如:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="record-by-ID" match="record" use="CON_ROW_ID"/>
<xsl:template match="/">
<output>
<!-- for each first record in its group -->
<xsl:for-each select="records/record[count(.|key('record-by-ID',CON_ROW_ID)[1]) = 1]">
<!-- sort the group by score -->
<xsl:for-each select="key('record-by-ID',CON_ROW_ID)">
<xsl:sort select="SCORE" order="descending"/>
<!-- output the highest scoring record -->
<xsl:if test="position() = 1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
每个唯一的CON_ROW_ID应该取最高分,然后 以SCORE降序再次返回这些。
如果你的处理器支持一些基本的EXSLT功能,那么这可能非常简短和甜蜜:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:set="http://exslt.org/sets"
xmlns:math="http://exslt.org/math"
extension-element-prefixes="set math">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="record-by-ID" match="record" use="CON_ROW_ID"/>
<xsl:template match="/">
<output>
<xsl:for-each select="set:distinct(records/record/CON_ROW_ID)">
<xsl:sort select="math:max(key('record-by-ID', .)/SCORE)" order="descending"/>
<xsl:copy-of select="math:highest(key('record-by-ID', .)/SCORE)/parent::record"/>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
否则你需要两次通过(和在过程中使用EXSLT node-set()函数):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="record-by-ID" match="record" use="CON_ROW_ID"/>
<xsl:template match="/">
<!-- FIRST PASS -->
<xsl:variable name="highest-scoring-records">
<!-- for each first record in its group -->
<xsl:for-each select="records/record[count(.|key('record-by-ID',CON_ROW_ID)[1]) = 1]">
<!-- sort the group by score -->
<xsl:for-each select="key('record-by-ID',CON_ROW_ID)">
<xsl:sort select="SCORE" order="descending"/>
<!-- output the highest scoring record -->
<xsl:if test="position() = 1">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:variable>
<!-- OUTPUT -->
<output>
<xsl:for-each select="exsl:node-set($highest-scoring-records)/record">
<xsl:sort select="SCORE" order="descending"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>