XSLT处理含嵌套元素字符串:保留anchor移除方括号的实现问题
TEI转换问题:保留嵌套
<anchor>元素的解决方案 输入结构
转换前的<hi>元素结构:
<hi rendition="#rf-Lyricist"> [Lyricist: <anchor xml:id="w1s"/>Some Name]<anchor xml:id="w1e"/> </hi>
期望输出
需要将<hi>转为<note>,同时把文本外的方括号替换为<supplied>嵌套,且保留所有<anchor>元素:
<note type="lyricist"> <supplied reason="provided-by-editor" cert="1" resp="#NN"> Lyricist: <anchor xml:id="w1s"/>Some Name<anchor xml:id="w1e"/> </supplied> </note>
现有代码的问题
之前尝试用<xsl:analyze-string>和translate()处理,但结果丢失了所有<anchor>元素:
<note type="lyricist"> <supplied reason="provided-by-editor" cert="1" resp="#ND"> Lyricist: Some Name </supplied> </note>
原因是select="."会把整个<hi>节点序列化为纯文本,嵌套的<anchor>元素被忽略,translate()只能处理字符串,自然保留不了节点结构。
正确的XSLT实现
不要用字符串处理,直接操作节点树,只处理文本节点中的括号,保留其他元素:
基础通用版(移除所有文本中的方括号)
<!-- 匹配目标hi元素,转换为note --> <xsl:template match="tei:hi[@rendition='#rf-Lyricist']"> <note type="lyricist" xmlns="http://www.tei-c.org/ns/1.0"> <supplied reason="provided-by-editor" cert="1" resp="#NN" xmlns="http://www.tei-c.org/ns/1.0"> <!-- 处理hi的所有子节点 --> <xsl:apply-templates select="node()"/> </supplied> </note> </xsl:template> <!-- 处理文本节点,移除所有方括号 --> <xsl:template match="text()"> <xsl:value-of select="translate(., '[]', '')"/> </xsl:template> <!-- 原样保留anchor元素 --> <xsl:template match="tei:anchor"> <xsl:copy-of select="."/> </xsl:template>
精准版(仅移除首尾的方括号,避免误删中间内容)
<xsl:template match="tei:hi[@rendition='#rf-Lyricist']"> <note type="lyricist" xmlns="http://www.tei-c.org/ns/1.0"> <supplied reason="provided-by-editor" cert="1" resp="#NN" xmlns="http://www.tei-c.org/ns/1.0"> <xsl:for-each select="node()"> <xsl:choose> <!-- 处理第一个文本节点,去掉开头的[ --> <xsl:when test="position()=1 and self::text()"> <xsl:value-of select="substring-after(., '[')"/> </xsl:when> <!-- 处理最后一个文本节点,去掉结尾的] --> <xsl:when test="position()=last() and self::text()"> <xsl:value-of select="substring-before(., ']')"/> </xsl:when> <!-- 其他节点原样输出 --> <xsl:otherwise> <xsl:copy-of select="."/> </xsl:otherwise> </xsl:choose> </xsl:for-each> </supplied> </note> </xsl:template>
内容的提问来源于stack exchange,提问作者OttoMan
相关产品推荐
相关产品推荐

