如何通过XSLT变量值选取节点?信用卡数据提取问题求助
问题分析与解决方案
你的问题出在两个核心点上:
1. 动态节点选择语法错误
XSLT 1.0不支持直接用变量$inputname作为元素名称来选择节点,比如root/MilleniumCreditCard/$inputname这种写法是无效的。要实现动态节点选择,需要通过匹配节点的本地名称来完成,语法为*[local-name() = $inputname]。
2. 节点存在性测试逻辑不严谨
root/MilleniumCreditCard != ''这种判断方式是在检查节点的字符串值是否非空,而非节点本身是否存在。如果节点存在但内容为空,这个测试会返回false。正确的节点存在性判断应该直接写root/MilleniumCreditCard(节点存在时测试结果为true),或者使用XSLT 2.0+支持的exists(root/MilleniumCreditCard)。
修正后的通用模板
<xsl:template name="commontemplate"> <xsl:param name="inputname" /> <xsl:choose> <xsl:when test="root/MilleniumCreditCard"> <xsl:value-of select="root/MilleniumCreditCard/*[local-name() = $inputname]" /> </xsl:when> <xsl:when test="root/VisaCreditCard"> <xsl:value-of select="root/VisaCreditCard/*[local-name() = $inputname]" /> </xsl:when> <xsl:when test="root/OtherTypeCreditCard"> <xsl:value-of select="root/OtherTypeCreditCard/*[local-name() = $inputname]" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="''"/> </xsl:otherwise> </xsl:choose> </xsl:template>
更简洁的优化写法
既然输入XML每次仅包含一种信用卡类型,完全可以不用逐个判断类型,直接匹配root下的所有信用卡节点,再提取目标子元素:
XSLT 2.0+版本(支持ends-with)
<xsl:template name="commontemplate"> <xsl:param name="inputname" /> <xsl:value-of select="root/*[local-name() ends-with('CreditCard')]/*[local-name() = $inputname]" /> </xsl:template>
XSLT 1.0版本(兼容写法)
<xsl:template name="commontemplate"> <xsl:param name="inputname" /> <xsl:value-of select="root/*[contains(local-name(), 'CreditCard')]/*[local-name() = $inputname]" /> </xsl:template>
这种写法无需维护多个xsl:when分支,后续新增信用卡类型也不用修改模板,更贴合“通用模板”的设计初衷。
最终输出效果
使用修正后的模板处理你的输入XML,会得到期望的结果:
<output> <Limit>20</Limit> <overdraft>yes</overdraft> </output>
内容的提问来源于stack exchange,提问作者Biltu - Technology
相关产品推荐
相关产品推荐

