XSLT2中如何比较子节点并高亮设备历史数据差异?
用XSLT 2.0对比设备历史数据并高亮差异
嘿,作为XSLT新手,你这个需求其实可以通过拆分字符串、对比相邻节点值来实现。咱们一步步来改造你的代码,实现高亮变更值的效果:
首先,你的原XML里两个<Details>的DeviceInfo只有id2的值不同,我们需要把每个键值对拆出来,和前一条记录的对应值对比,不一样的就高亮(比如加粗)。
核心思路
- 升级XSLT版本到2.0(你的原代码是1.0,要用上2.0的字符串拆分函数)
- 把
DeviceInfo的字符串拆成独立的键值对(比如Id1:459800800691拆成键Id1和值459800800691) - 对每个键值对,和前一个
<Details>节点的对应值做比较 - 若值不同,用自定义CSS样式或
<b>标签高亮显示
修改后的完整XSLT代码
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 主模板,生成HTML结构 --> <xsl:template match="/DeviceHistory"> <html> <head> <!-- 自定义高亮样式,比原生<b>更灵活 --> <style> .highlight { font-weight: bold; color: #dc3545; } table { border-collapse: collapse; margin: 10px 0; } td { padding: 8px; border: 1px solid #ddd; } </style> </head> <body> <xsl:apply-templates select="Part"/> </body> </html> </xsl:template> <!-- 处理Part节点,生成外层表格 --> <xsl:template match="Part"> <h3>设备历史:<xsl:value-of select="@Name"/></h3> <table border='1'> <tr> <xsl:for-each select="Details"> <td class='FRUVal' valign='middle' width='380'> <table> <tr><td><strong>日期:</strong><xsl:apply-templates select="Date"/></td></tr> <tr> <td> <strong>设备信息:</strong> <!-- 按空格拆分DeviceInfo为单个键值项 --> <xsl:for-each select="tokenize(DeviceInfo, '\s+')"> <!-- 把每个键值项拆成键和值(按冒号分割) --> <xsl:variable name="currentKey" select="tokenize(., ':')[1]"/> <xsl:variable name="currentValue" select="tokenize(., ':')[2]"/> <!-- 获取前一个Details节点中对应键的值 --> <xsl:variable name="prevValue"> <xsl:if test="position() > 1"> <xsl:value-of select="tokenize(preceding-sibling::Details[1]/DeviceInfo, '\s+')[tokenize(., ':')[1] = $currentKey]/tokenize(., ':')[2]"/> </xsl:if> </xsl:variable> <!-- 输出逻辑:第一个节点直接输出;后续节点对比值,不同则高亮 --> <xsl:value-of select="$currentKey"/>: <xsl:choose> <xsl:when test="position() = 1"> <xsl:value-of select="$currentValue"/> </xsl:when> <xsl:when test="$currentValue != $prevValue"> <span class="highlight"><xsl:value-of select="$currentValue"/></span> </xsl:when> <xsl:otherwise> <xsl:value-of select="$currentValue"/> </xsl:otherwise> </xsl:choose> <!-- 键值对之间加空格分隔 --> <xsl:if test="position() != last()"> </xsl:if> </xsl:for-each> </td> </tr> </table> </td> </xsl:for-each> </tr> </table> </xsl:template> </xsl:stylesheet>
代码关键点解释
tokenize()函数:XSLT2.0新增的字符串拆分工具,这里用\s+匹配任意空格拆分整个DeviceInfo,再用:拆分单个键值项,轻松提取键和值。preceding-sibling::Details[1]:精准获取当前<Details>的前一个兄弟节点,用来提取历史数据做对比。- 高亮逻辑:第一个
<Details>没有历史数据直接输出;后续节点对比当前值和历史值,不同则应用highlight样式,视觉上清晰区分变更内容。 - 样式优化:加入了基础CSS让表格更美观,高亮用红色加粗,你可以根据需求调整颜色、字体等样式。
渲染效果
用你的XML测试时,第二个<Details>里的id2:000008会显示为红色加粗样式,和第一个的id2:000007形成明显对比,完美体现数据变更。
内容的提问来源于stack exchange,提问作者Apoorva Raju
相关产品推荐
相关产品推荐

