如何在XSLT 2.0中递归匹配另一模板内的模板并取值?
解决XSLT中提取值并插入/后的问题
嘿,我完全懂你这几天被这个问题卡得难受——想把xsl:function输出了整个节点而非仅需要的值,对吧?别着急,咱们来一步步搞定它。
首先得明确核心:你要的是
方法一:用模板匹配(最直观的常规写法)
先假设你的源XML结构大概是这样(如果实际结构不同,调整XPath路径就行):
<library> <book> <author>George Orwell</author> <title>1984</title> </book> <feedback>A timeless classic about totalitarianism</feedback> </library>
我们可以用XSLT的身份模板复制所有默认节点,然后专门针对<book>节点做自定义处理,在复制完所有子节点后插入
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 身份模板:默认复制所有节点、属性 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 自定义处理book节点 --> <xsl:template match="book"> <xsl:copy> <!-- 先复制book下原有的所有子节点(比如author、title) --> <xsl:apply-templates select="node()"/> <!-- 插入新的feedback节点,只取原feedback的文本内容 --> <feedback> <xsl:value-of select="/library/feedback"/> </feedback> </xsl:copy> </xsl:template> </xsl:stylesheet>
如果你的<feedback><text>...</text><rating>5</rating></feedback>),那就把xsl:value-of换成xsl:copy-of select="/library/feedback/node()",这样就能完整复制
方法二:修正你的xsl:function
如果坚持要用函数来实现,问题大概率出在你的函数返回了整个
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://example.com/myfunctions"> <!-- 身份模板依旧保留 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 自定义函数,返回feedback的文本内容 --> <xsl:function name="my:getFeedbackContent"> <xsl:param name="currentNode"/> <!-- 注意XPath路径:从当前节点(比如author)找到父节点book,再找兄弟节点feedback --> <xsl:value-of select="$currentNode/../feedback"/> <!-- 若要保留子节点,换成:<xsl:copy-of select="$currentNode/../feedback/node()"/> --> </xsl:function> <!-- 处理author节点,在其后插入feedback内容 --> <xsl:template match="author"> <xsl:copy-of select="."/> <!-- 先复制原author节点 --> <!-- 调用函数生成新的feedback节点 --> <feedback> <xsl:value-of select="my:getFeedbackContent(.)"/> </feedback> </xsl:template> </xsl:stylesheet>
这里要注意XPath的路径正确性:如果$currentNode/../feedback就能准确定位到它;如果结构更深,就调整路径层级。
关键提醒点
- 用
xsl:value-of获取纯文本内容,用xsl:copy-of获取节点的内部子结构 - 务必确保XPath路径能精准定位到目标
节点,别写错层级 - 如果你用的是XSLT 1.0,函数需要放在命名空间下(XSLT 2.0+支持无命名空间函数,但还是建议加命名空间避免冲突)
内容的提问来源于stack exchange,提问作者Sojimanatsu
相关产品推荐
相关产品推荐

