XPath/XSL问题:无法用node-set检索节点,需关联两表生成单表
解决你的两个XSL问题:node-set使用与表关联输出
一、搞定node-set无法检索节点元素的问题
从你XML里的msxsl命名空间来看,你应该是在XSLT 1.0环境下工作——这个版本有个限制:如果变量存的是结果树片段(比如用<xsl:variable>直接包裹节点,而不是通过select直接获取节点集),是没法直接用XPath查询的,必须先把它转换成节点集才行。
具体操作步骤:
- 先确保你的XSL文件里已经声明了
msxsl命名空间:<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"> - 当需要访问结果树片段里的节点时,用
msxsl:node-set()函数做转换:<!-- 假设你有一个存储结果树片段的变量 --> <xsl:variable name="myFragment"> <row><data>示例数据</data></row> </xsl:variable> <!-- 转换后就能正常用XPath遍历了 --> <xsl:for-each select="msxsl:node-set($myFragment)/row"> <p><xsl:value-of select="data"/></p> </xsl:for-each>
要是你用的是XSLT 2.0及以上版本,就没这个麻烦了,变量默认就是可查询的节点集。
二、关联两张表输出单个整合表
要把"Conventional Display"表中值为BASICSA 的行,和"All Rates"表的对应数据关联起来,用<xsl:key>建立索引是最高效的方式,避免嵌套循环的冗余。
完整XSL示例代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"> <!-- 为All Rates表建立索引,用每行第一个Td的值作为匹配键 --> <xsl:key name="rateMatch" match="Table[@name='All Rates']/Tbody/Tr" use="normalize-space(Td[1])"/> <xsl:template match="/"> <html> <body> <table border="1"> <!-- 遍历Conventional Display表中匹配BASICSA的行 --> <xsl:for-each select="Rates/TableList/Table[@name='Conventional Display']/Tbody/Tr[normalize-space(Td[1])='BASICSA']"> <tr> <!-- 先输出Conventional Display表中的原有列 --> <xsl:for-each select="Td"> <td><xsl:value-of select="."/></td> </xsl:for-each> <!-- 关联并输出All Rates表中对应的后续列 --> <xsl:for-each select="key('rateMatch', normalize-space(Td[1]))/Td[position()>1]"> <td><xsl:value-of select="."/></td> </xsl:for-each> </tr> </xsl:for-each> </table> </body> </html> </xsl:template> </xsl:stylesheet>
关键细节说明
normalize-space(Td[1])是为了去掉BASICSA后面的空格,避免因为空格导致匹配失败;<xsl:key>提前把All Rates表的行和匹配键做了映射,后续用key()函数可以瞬间找到对应行,比嵌套循环效率高很多;- 如果需要输出"Conventional Display"的所有行并关联对应数据,只需要删掉
Tr[normalize-space(Td[1])='BASICSA']这个筛选条件就行。
内容的提问来源于stack exchange,提问作者Cheong Ze Wei
相关产品推荐
相关产品推荐

