我有一个XML结构,如下所示
<Categories>
<cat>Video</cat>
<cat>Audio</cat>
<cat>Hybrid</cat>
</Categories>
在这样的查找XML中有一个可用于此类别的映射
<Lookup>
<cat>Video</cat>
<mapping>1</mapping>
</Lookup>
<Lookup>
<cat>Audio</cat>
<mapping>2</mapping>
</Lookup>
<Lookup>
<cat>Hybrid</cat>
<mapping>3</mapping>
</Lookup>
</ValueSet>
现在我正在寻找一个XSLT解决方案,它可以在不使用节点集扩展功能的情况下将Max值作为输出返回给我。
以下是我的测试用例
测试案例1:
输入:
<Categories>
<cat>Video</cat>
<cat>Audio</cat>
<cat>Hybrid</cat>
</Categories>
预期产出3
测试案例2:
输入:
<Categories>
<cat>Video</cat>
<cat>Hybrid</cat>
</Categories>
预期产出3
测试案例3:
输入:
<Categories>
<cat>Video</cat>
<cat>Audio</cat>
</Categories>
预期产出2
测试案例4:
输入:
<Categories>
<cat>Audio</cat>
<cat>Hybrid</cat>
</Categories>
预期产出3
测试案例5:
输入:
<Categories>
<cat>Video</cat>
</Categories>
预期产出1
提前致谢。
从评论中更新:
查找我的信息不是 可以加载[使用
document()
功能]。我需要for-each
类别输入然后导出 查找值。在那之后,我需要 获得最大化。我有xsl提供的扩展程序 引擎处理器来实现这一点 xslt如下:
<xsl:value-of select='xx:lookupValue("MappingXML","Category",.,"COL1")'/>
此函数返回字符串。这个 函数不返回nodeset。一世 通过捕获所有来尝试变量 执行后的派生值
for-each
,但需要进一步处理 这个变量输出(RTF),在XSLt中 1.0,我没有处理任何node-set()函数。
答案 0 :(得分:2)
来自OP的评论:
我有xsl提供的扩展程序 引擎处理器来实现这一点 xslt如下:
<xsl:value-of select='xx:lookupValue("MappingXML","Category",.,"COL1")'/>
- satish
这适用于XSLT 2.0并且必须在XSLT 1.0中工作(只需删除<xsl:function>
并使用您的扩展功能):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xx="my:xx"
>
<xsl:output omit-xml-declaration="yes"/>
<xx:lookup>
<ValueSet>
<Lookup>
<cat>Video</cat>
<mapping>1</mapping>
</Lookup>
<Lookup>
<cat>Audio</cat>
<mapping>2</mapping>
</Lookup>
<Lookup>
<cat>Hybrid</cat>
<mapping>3</mapping>
</Lookup>
</ValueSet>
</xx:lookup>
<xsl:variable name="vlookupDoc" select="document('')/*/xx:lookup"/>
<xsl:template match="/*">
<xsl:call-template name="getMax">
<xsl:with-param name="pNodes" select="cat"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="getMax">
<xsl:param name="pcurrMax" select="-9999999999"/>
<xsl:param name="pNodes"/>
<xsl:choose>
<xsl:when test="not($pNodes)">
<xsl:value-of select="$pcurrMax"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vNewVal" select=
"number(xx:lookupValue($vlookupDoc,$pNodes[1]))"/>
<xsl:call-template name="getMax">
<xsl:with-param name="pNodes" select="$pNodes[position() >1]"/>
<xsl:with-param name="pcurrMax" select=
"number(($pcurrMax >= $vNewVal))*$pcurrMax
+
number(($vNewVal > $pcurrMax))*$vNewVal"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:function name="xx:lookupValue">
<xsl:param name="pLookupDoc"/>
<xsl:param name="pCat"/>
<xsl:value-of select=
"$pLookupDoc/*/*[cat=$pCat]/mapping"/>
</xsl:function>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<Categories>
<cat>Video</cat>
<cat>Audio</cat>
<cat>Hybrid</cat>
</Categories>
产生了想要的正确结果:
3
转换为XSLT 1.0的代码:
<xsl:stylesheet version="12.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xx="Your Namespace Here"
>
<xsl:output omit-xml-declaration="yes"/>
<xx:lookup>
<ValueSet>
<Lookup>
<cat>Video</cat>
<mapping>1</mapping>
</Lookup>
<Lookup>
<cat>Audio</cat>
<mapping>2</mapping>
</Lookup>
<Lookup>
<cat>Hybrid</cat>
<mapping>3</mapping>
</Lookup>
</ValueSet>
</xx:lookup>
<!-- You probably don't need this and the above embedded XML -->
<xsl:variable name="vlookupDoc" select="document('')/*/xx:lookup"/>
<xsl:template match="/*">
<xsl:call-template name="getMax">
<xsl:with-param name="pNodes" select="cat"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="getMax">
<xsl:param name="pcurrMax" select="-9999999999"/>
<xsl:param name="pNodes"/>
<xsl:choose>
<xsl:when test="not($pNodes)">
<xsl:value-of select="$pcurrMax"/>
</xsl:when>
<xsl:otherwise>
<!-- Change the call of the ext. function as appr. -->
<xsl:variable name="vNewVal" select=
"number(xx:lookupValue($vlookupDoc,$pNodes[1]))"/>
<xsl:call-template name="getMax">
<xsl:with-param name="pNodes" select="$pNodes[position() >1]"/>
<xsl:with-param name="pcurrMax" select=
"($pcurrMax >= $vNewVal)*$pcurrMax
+
($vNewVal > $pcurrMax)*$vNewVal"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
这是XSLT的经典最大算法:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xx="extension-URI">
<xsl:template match="/">
<xsl:for-each select="Categories/cat">
<xsl:sort select="xx:lookupValue('MappingXML',
'Category',
.,
'COL1')"
data-type="number"
order="descending"/>
<xsl:if test="position()=1">
<xsl:value-of select="xx:lookupValue('MappingXML',
'Category',
.,
'COL1')"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
当然,你的限制和映射强制这个添加一个额外调用扩展函数...如果这是一个很大的代价,你应该逐个节点地递归(或者在下面的兄弟轴上进行交叉)解决方案,如@Dimitre。
在XPath / XSLT 2.0中,它更容易:
max(Categories/cat/xx:lookupValue('MappingXML','Category',.,'COL1')
答案 2 :(得分:0)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:variable name="docLookup" select="document('lookup_file.xml')/*/Lookup"/>
<xsl:variable name="avElms" select="cat"/>
<xsl:value-of select="$docLookup/mapping
[not(. < ../../Lookup[cat = $avElms]/mapping)]/text()"/>
</xsl:template>
</xsl:stylesheet>
结果:
<Categories>
<cat>Video</cat>
<cat>Audio</cat>
<cat>Hybrid</cat>
</Categories>
结果为3
<Categories>
<cat>Video</cat>
<cat>Hybrid</cat>
</Categories>
结果为3
<Categories>
<cat>Video</cat>
<cat>Audio</cat>
</Categories>
结果为2
<Categories>
<cat>Audio</cat>
<cat>Hybrid</cat>
</Categories>
结果为3
<Categories>
<cat>Video</cat>
</Categories>
结果为1