如何在XSLT中按分隔符位置分配FODepartment_LX系列变量?
XSLT实现按分隔符位置生成指定变量的方案
需求说明
需要在XSLT中为名为FODepartment_LX的变量赋值:
- X代表从最左侧开始的分隔符(
+)的位置,最大位置为10 - 若对应位置无有效取值,剩余变量设为空字符串(
'')
输入XML示例
<EmpJob> <EmpJob> <ConcatDepartment>+Local_Functions+Group_Functions+Group_Owners+Group_Managers+Group_Leads+Interim_Services</ConcatDepartment> </EmpJob> </EmpJob>
期望输出变量(用于后续处理)
<xsl:variable name="FODepartment_L10" select=""/> <xsl:variable name="FODepartment_L9" select=""/> <xsl:variable name="FODepartment_L8" select=""/> <xsl:variable name="FODepartment_L7" select=""/> <xsl:variable name="FODepartment_L6" select="Interim_Services"/> <xsl:variable name="FODepartment_L5" select="Group_Leads"/> <xsl:variable name="FODepartment_L4" select="Group_Managers"/> <xsl:variable name="FODepartment_L3" select="Group_Owners"/> <xsl:variable name="FODepartment_L2" select="Group_Functions"/> <xsl:variable name="FODepartment_L1" select="Local_Functions"/>
实现方案(XSLT 2.0及以上)
利用tokenize()函数拆分字符串,再通过循环生成对应变量:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <!-- 拆分ConcatDepartment内容,按+分隔 --> <xsl:variable name="tokenizedDepts" select="tokenize(EmpJob/EmpJob/ConcatDepartment, '\+')"/> <!-- 循环生成L1到L10的变量 --> <xsl:for-each select="1 to 10"> <xsl:variable name="index" select="."/> <!-- 拆分后第一个元素为空,实际部门从第2个元素开始对应L1 --> <xsl:variable name="deptValue" select="if ($index <= count($tokenizedDepts) - 1) then $tokenizedDepts[$index + 1] else ''"/> <!-- 声明变量供后续使用 --> <xsl:variable name="FODepartment_L{$index}" select="$deptValue"/> <!-- 以下为展示输出用,实际业务可省略 --> <xsl:copy-of select="element(xsl:variable, attribute(name, concat('FODepartment_L', $index)), attribute(select, if ($deptValue != '') then $deptValue else '') )"/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
代码说明
- 字符串拆分:
tokenize()函数将目标字符串按+拆分,得到的序列第一个元素为空(因原字符串以+开头),后续元素依次为各部门值。 - 变量生成逻辑:通过
1 to 10循环覆盖所有位置,当索引小于等于有效部门数量时取对应值,超出则设为空字符串。 - 动态变量名:XSLT 2.0支持动态构造变量名,可直接在模板中使用
$FODepartment_L{$index}调用对应变量。
兼容XSLT 1.0的方案
若只能使用XSLT 1.0,可通过递归模板实现字符串拆分:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"> <xsl:template match="/"> <xsl:variable name="deptString" select="EmpJob/EmpJob/ConcatDepartment"/> <!-- 递归拆分字符串为节点集 --> <xsl:variable name="deptList"> <xsl:call-template name="splitString"> <xsl:with-param name="input" select="$deptString"/> <xsl:with-param name="delimiter" select="'+'"/> </xsl:call-template> </xsl:variable> <xsl:variable name="depts" select="msxsl:node-set($deptList)/dept"/> <!-- 生成L1到L10变量 --> <xsl:for-each select="1 to 10"> <xsl:variable name="index" select="."/> <xsl:variable name="deptValue" select="if ($index <= count($depts) - 1) then $depts[$index + 1] else ''"/> <xsl:variable name="FODepartment_L{$index}" select="$deptValue"/> <!-- 展示输出用,实际业务可省略 --> <xsl:element name="xsl:variable"> <xsl:attribute name="name">FODepartment_L<xsl:value-of select="$index"/></xsl:attribute> <xsl:attribute name="select"> <xsl:if test="$deptValue != ''"> <xsl:value-of select="$deptValue"/> </xsl:if> </xsl:attribute> </xsl:element> </xsl:for-each> </xsl:template> <!-- 递归拆分字符串的模板 --> <xsl:template name="splitString"> <xsl:param name="input"/> <xsl:param name="delimiter"/> <xsl:choose> <xsl:when test="contains($input, $delimiter)"> <dept><xsl:value-of select="substring-before($input, $delimiter)"/></dept> <xsl:call-template name="splitString"> <xsl:with-param name="input" select="substring-after($input, $delimiter)"/> <xsl:with-param name="delimiter" select="$delimiter"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <dept><xsl:value-of select="$input"/></dept> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
代码说明
- 递归拆分:通过
splitString模板将字符串拆分为节点集,再用msxsl:node-set()转换为可查询的节点集(不同处理器可能需替换为对应节点集转换函数,如EXSLT的exsl:node-set())。 - 变量生成逻辑:与XSLT 2.0方案一致,循环生成所有变量并赋值。
内容的提问来源于stack exchange,提问作者Pavan Kumar
相关产品推荐
相关产品推荐

