我想:
- 选择所有字符串值属性"foo",并将这些值存储在列表中
- 使用xslt中的一些映射将该列表中属性"foo"的每个值转换为一个数字
- 选择列表的最大值并输出
因此,给定以下xml:
<t>
<tag foo="A">apples</tag>
<tag foo="C">oranges</tag>
<tag foo="B">trees</tag>
</t>
以及以下映射:
<xsl:variable name="myMap">
<entry key="A">1</entry>
<entry key="B">2</entry>
<entry key="C">3</entry>
</xsl:variable>
输出为:
<max>3</max>
另一个问题是,为什么我不能缩进代码?我在放空位,但没用。
I这个标准的XSLT1.0转换(最像您的方法):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vrtfMap">
<entry key="A" value="1"/>
<entry key="B" value="2"/>
<entry key="C" value="3"/>
<entry key="X" value="8"/>
</xsl:variable>
<xsl:variable name="vMap" select=
"document('')/*/xsl:variable[@name = 'vrtfMap']/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@foo">
<xsl:attribute name="foo">
<xsl:value-of select="$vMap[@key = current()]/@value"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
当应用于以下XML文档时(因为您没有提供任何):
<t foo="X">
<a foo="A">
<b foo="B"/>
</a>
<c foo="C"/>
</t>
生成所需的正确结果:
<t foo="8">
<a foo="1">
<b foo="2"/>
</a>
<c foo="3"/>
</t>
解释:适当使用XSLTcurrent()
函数。
II。XSLT1.0解决方案,使用快捷键
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kValFromKey" match="entry/@value" use="../@key"/>
<xsl:variable name="vrtfMap">
<entry key="A" value="1"/>
<entry key="B" value="2"/>
<entry key="C" value="3"/>
<entry key="X" value="8"/>
</xsl:variable>
<xsl:variable name="vMap" select=
"document('')/*/xsl:variable[@name = 'vrtfMap']/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@foo">
<xsl:variable name="vCur" select="."/>
<xsl:attribute name="foo">
<xsl:for-each select="document('')">
<xsl:value-of select="key('kValFromKey', $vCur)"/>
</xsl:for-each>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
将此转换应用于同一XML文档(如上)时,会产生相同的正确结果。
解释:
使用
<xsl:for-each select="document('')">
将当前文档设置为样式表,以便key()
函数将使用为此文档构建的键索引。将模板匹配的节点保存在变量中,以便我们可以在
xsl:for-each
中使用它——这里不能正确使用current()
,因为它获取xsl:for-each
操作的当前节点。
更新:OP现在在一条评论中澄清说,他最大的问题是找到最大值。
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vrtfMap">
<entry key="A" value="1"/>
<entry key="B" value="2"/>
<entry key="C" value="3"/>
</xsl:variable>
<xsl:variable name="vMap" select=
"document('')/*/xsl:variable[@name = 'vrtfMap']/*"/>
<xsl:template match="/">
<xsl:variable name="vDoc" select="."/>
<xsl:variable name="vFoosMapped"
select="$vMap[@key = $vDoc/*/*/@foo]"/>
<max>
<xsl:value-of select=
"$vFoosMapped
[not($vFoosMapped/@value > @value)]
/@value
"/>
</max>
</xsl:template>
</xsl:stylesheet>
如果给定此XML文档(OP提供的文档缺少一个singlelr-top元素):
<t>
<tag foo="A">apples</tag>
<tag foo="C">oranges</tag>
<tag foo="B">trees</tag>
</t>
生成所需的正确结果:
<max>3</max>
备注:在XSLT1.0中计算最大值(或最小值——以类似的方式)的一种更有效的方法是这样做:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vrtfMap">
<entry key="A" value="1"/>
<entry key="B" value="2"/>
<entry key="C" value="3"/>
</xsl:variable>
<xsl:variable name="vMap" select=
"document('')/*/xsl:variable[@name = 'vrtfMap']/*"/>
<xsl:template match="/">
<xsl:variable name="vDoc" select="."/>
<xsl:variable name="vFoosMapped"
select="$vMap[@key = $vDoc/*/*/@foo]"/>
<max>
<xsl:for-each select="$vFoosMapped">
<xsl:sort select="@value" data-type="number" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="@value"/>
</xsl:if>
</xsl:for-each>
</max>
</xsl:template>
</xsl:stylesheet>
另一个问题是,为什么我不能缩进代码?我在放空位,但是它不起作用。
这是一个他们几个月都没能修复的bug。
很可能您正在使用IE。如果您的版本是9,请执行以下操作:
按F12。
在弹出的窗口中,点击最右边的菜单并选择:"文档模式:IE9标准"
现在,您应该能够看到带有缩进的代码。