如何用XSLT更新EDI转XML后BAK行第8个^分隔位的值?
问题分析与解决方案
原代码的问题
你使用的replace(., tokenize(.,'\\^')[9], 'NEW')存在两个核心问题:
- 匹配范围错误:
replace会替换字符串中所有与第9个token相同的内容,而非仅定位到第8个分隔位置的目标值,若其他位置出现相同文本会被误改。 - 空值处理失效:如果目标位置原本是空值,
tokenize返回的对应元素为空字符串,replace会替换所有空分隔的位置,导致结构混乱。
最优解决方案(XSLT 2.0+)
利用tokenize拆分字段后精准重组,既能处理长度不固定的字段,也能避免误替换问题:
<xsl:stylesheet version="2.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> <!-- 处理以BAK开头的data节点 --> <xsl:template match="data[starts-with(., 'BAK')]"> <data> <xsl:variable name="tokens" select="tokenize(., '\^')"/> <!-- 拼接前8个字段 + NEW + 第10个及以后的字段,用^分隔 --> <xsl:value-of select="string-join( ($tokens[position() le 8], 'NEW', $tokens[position() ge 10]), '^' )"/> </data> </xsl:template> </xsl:stylesheet>
代码说明
- 身份模板:确保非BAK开头的
data节点和其他XML结构原样输出。 - BAK节点处理:
- 用
tokenize(., '\^')将文本按^拆分为字段数组。 - 选取数组前8个字段,插入新值
NEW,再拼接第10个及以后的字段,最后用string-join重新组合为字符串。
- 用
测试结果
输入你的XML后,输出会符合预期:
<root> <data>ST^8^347</data> <data>BAK^00^A^100001396^20240102^^^^NEW^a</data> <data>REF^OQ^5004506</data> </root>
内容的提问来源于stack exchange,提问作者Adee
相关产品推荐
相关产品推荐

