如何在XSLT中通过ID引用获取并显示对应Item的名称
解决XSLT显示item名称而非ID的问题
问题背景
现有XML文档包含item节点(含id属性与NAME子节点)与owner节点,每个owner可通过property节点引用多个item。当前XSLT导出Max的所有item时,仅显示item的引用ID(如a01),需改为显示对应的NAME内容(如name of item a1)。
原XML代码
<?xml version="1.0" encoding="UTF-8"?> <MYDATA xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <item id="a01"> <NAME>name of item a1</NAME> </item> <item id="a02"> <NAME>name of item a2</NAME> </item> <item id="a03"> <NAME>name of item a3</NAME> </item> <owner> <name>Max</name> <owns> <property prop_id="a01"> <DATE_BOUGHT>1</DATE_BOUGHT> </property> <property prop_id="a02"> <DATE_BOUGHT>2</DATE_BOUGHT> </property> </owns> </owner> <owner> <name>Anna</name> <owns> <property prop_id="a01"> <DATE_BOUGHT>3</DATE_BOUGHT> </property> <property prop_id="a03"> <DATE_BOUGHT>2</DATE_BOUGHT> </property> </owns> </owner> </MYDATA>
原XSLT代码(存在问题)
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <html> <head> <title>Max's items</title> </head> <body> <h1>Max's items</h1> <h2>List of all items owned by Max </h2> <table border="1"> <tr bgcolor="#9acd32"> <th align="left">Title</th> <th align="left">borrowed since</th> </tr> <xsl:for-each select="MYDATA/owner[name = 'Max']/owns/property"> <xsl:sort select="DATE_BOUGHT"/> <xsl:key name="item-by-id" match="item" use="@id"/> <tr> <td> <xsl:value-of select="key('item-by-id', @prop_id)/NAME"/> </td> <td> <xsl:value-of select="DATE_BOUGHT"/> </td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
当前错误输出
<html> <head> <META http-equiv="Content-Type" content="text/html"> <title>Max's items</title> </head> <body> <h1>Max's items</h1> <h2>List of all items owned by Max </h2> <table border="1"> <tr bgcolor="#9acd32"> <th align="left">Name</th> <th align="left">DATE_BOUGHT</th> </tr> <tr> <td>a01</td> <td>1</td> </tr> <tr> <td>a02</td> <td>2</td> </tr> </table> </body> </html>
问题原因
原XSLT中<xsl:key>定义在<xsl:for-each>内部,违反了XSLT 1.0的规则:key必须定义在stylesheet的顶层(直接作为<xsl:stylesheet>的子节点),导致key未生效,无法通过prop_id找到对应的item节点,最终 fallback 显示了property的prop_id属性值。
修改后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 将key移到顶层,全局生效 --> <xsl:key name="item-by-id" match="item" use="@id"/> <xsl:template match="/"> <html> <head> <title>Max's items</title> </head> <body> <h1>Max's items</h1> <h2>List of all items owned by Max </h2> <table border="1"> <tr bgcolor="#9acd32"> <!-- 修正表头文字,匹配期望输出 --> <th align="left">Name</th> <th align="left">DATE_BOUGHT</th> </tr> <xsl:for-each select="MYDATA/owner[name = 'Max']/owns/property"> <xsl:sort select="DATE_BOUGHT"/> <tr> <td> <!-- 通过key匹配item,取出NAME值 --> <xsl:value-of select="key('item-by-id', @prop_id)/NAME"/> </td> <td> <xsl:value-of select="DATE_BOUGHT"/> </td> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
修改说明
- 移动key位置:将
<xsl:key>从for-each内部移到stylesheet顶层,确保全局可访问,正确建立item的id索引。 - 修正表头文字:将
Title改为Name,borrowed since改为DATE_BOUGHT,与期望输出一致。 - 保留原有逻辑:保留按
DATE_BOUGHT排序、筛选Max的item等逻辑,确保功能不受影响。
内容的提问来源于stack exchange,提问作者safex
相关产品推荐
相关产品推荐

