XSLT中如何用FOR循环遍历@cpu[N]属性并自动取值?
解决XSLT中批量遍历带数字后缀的CPU属性问题
我懂你这种痛点——手动写@cpu0到@cpu19简直是重复劳动,想靠循环自动化处理太合理了!你之前用@cpu[0]的写法其实踩了XPath的语法坑:XPath里的方括号是用来过滤节点的,不是属性名的一部分,所以这种写法根本匹配不到对应的属性,自然没输出。
咱们换个思路,动态构造属性名来遍历就解决问题了,下面分两种常见的XSLT版本给出方案:
方案一:XSLT 2.0+(推荐,语法更简洁)
XSLT 2.0及以上支持原生的for循环,直接生成索引数字,再拼接成属性名匹配即可:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/root"> <div class="cpu-list"> <!-- 循环0到19,覆盖20个CPU属性 --> <xsl:for-each select="0 to 19"> <xsl:variable name="index" select="."/> <!-- 动态构造属性名并匹配 --> <xsl:variable name="cpu-attribute" select="current()/@*[local-name() = concat('cpu', $index)]"/> <!-- 输出属性值,即使属性不存在也能优雅处理 --> <p> CPU<xsl:value-of select="$index"/>: <xsl:value-of select="$cpu-attribute" default="未配置"/> </p> </xsl:for-each> </div> </xsl:template> </xsl:stylesheet>
如果不确定CPU的数量,还可以自动抓取所有带cpu前缀的属性,提取数字后缀排序后遍历,完全不用硬编码数量:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/root"> <div class="cpu-list"> <!-- 筛选所有以cpu开头的属性,按数字后缀排序 --> <xsl:for-each select="@*[starts-with(local-name(), 'cpu')]"> <xsl:sort select="number(substring-after(local-name(), 'cpu'))" data-type="number"/> <p> CPU<xsl:value-of select="substring-after(local-name(), 'cpu')"/>: <xsl:value-of select="."/> </p> </xsl:for-each> </div> </xsl:template> </xsl:stylesheet>
方案二:XSLT 1.0(兼容旧环境)
XSLT 1.0没有原生的for循环,需要用递归模板来实现循环逻辑:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 主模板触发递归循环 --> <xsl:template match="/root"> <div class="cpu-list"> <xsl:call-template name="loop-cpu"> <xsl:with-param name="current-index" select="0"/> <xsl:with-param name="max-index" select="19"/> <!-- 定义最大CPU索引 --> </xsl:call-template> </div> </xsl:template> <!-- 递归循环模板 --> <xsl:template name="loop-cpu"> <xsl:param name="current-index"/> <xsl:param name="max-index"/> <!-- 当索引未超过最大值时继续循环 --> <xsl:if test="$current-index <= $max-index"> <xsl:variable name="attr-name" select="concat('cpu', $current-index)"/> <p> CPU<xsl:value-of select="$current-index"/>: <xsl:value-of select="@*[name() = $attr-name]" /> </p> <!-- 递归调用,索引自增1 --> <xsl:call-template name="loop-cpu"> <xsl:with-param name="current-index" select="$current-index + 1"/> <xsl:with-param name="max-index" select="$max-index"/> </xsl:call-template> </xsl:if> </xsl:template> </xsl:stylesheet>
关键要点总结
- 不要用
@cpu[0]这种错误写法,XPath的方括号不能用来拼接属性名; - 用
concat('cpu', $index)动态构造属性名,再通过@*[local-name() = 构造的属性名]匹配目标属性; - 如果不需要固定数量,优先选择自动筛选
cpu前缀属性的方式,扩展性更强。
内容的提问来源于stack exchange,提问作者Jakub Oškera
相关产品推荐
相关产品推荐

