如何编写XSLT 1.0实现XML转仅含指定映射字段的CSV?
修正XSLT 1.0实现XML到CSV的指定字段映射转换
问题分析
当前XSLT在生成数据行时,遍历了<position>下的所有子节点,导致输出大量未在<headerFieldsMap>中定义的字段(如ReportsToEmail),不符合仅保留指定映射字段的要求。需要调整数据行的生成逻辑,严格按照<headerFieldsMap>中定义的字段顺序和名称提取对应值。
修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8"/> <xsl:variable name="delimiter" select="','"/> <!-- 预存headerFieldsMap的字段节点,方便后续复用 --> <xsl:variable name="headerFields" select="/root/headerFieldsMap/*"/> <xsl:template match="/"> <!-- Header row - 保持原有逻辑不变 --> <xsl:for-each select="$headerFields"> <xsl:value-of select="."/> <xsl:if test="position() != last()"> <xsl:value-of select="$delimiter"/> </xsl:if> </xsl:for-each> <xsl:text> </xsl:text> <!-- Data rows - 按headerFields的字段顺序提取对应值 --> <xsl:for-each select="/root/psPositions/position"> <xsl:variable name="currentPosition" select="."/> <xsl:for-each select="$headerFields"> <xsl:variable name="fieldName" select="name()"/> <!-- 获取当前position中对应字段的值 --> <xsl:variable name="fieldValue" select="$currentPosition/*[name() = $fieldName]"/> <!-- 保留原有的StdHoursFreq替换逻辑 --> <xsl:choose> <xsl:when test="$fieldName = 'StdHoursFreq' and $fieldValue = 'W'"> <xsl:text>Weekly</xsl:text> </xsl:when> <xsl:otherwise> <xsl:value-of select="$fieldValue"/> </xsl:otherwise> </xsl:choose> <xsl:if test="position() != last()"> <xsl:value-of select="$delimiter"/> </xsl:if> </xsl:for-each> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet>
修改关键点说明
- 预存header字段集合:定义变量
$headerFields存储<headerFieldsMap>下的所有字段节点,避免重复查找,提升效率。 - 数据行遍历逻辑调整:不再遍历
<position>的所有子节点,而是遍历$headerFields,通过字段名称精准匹配<position>中的对应节点。 - 处理缺失字段:如果
<position>中没有某个映射字段,会自动输出空值,保证CSV列数与表头完全对应。 - 保留原有业务逻辑:保留了
StdHoursFreq字段值为W时替换为Weekly的处理规则。
验证效果
修正后的XSLT生成的CSV将严格按照<headerFieldsMap>定义的表头顺序输出,仅包含指定字段的值,不会出现多余字段,与期望输出完全一致。
内容的提问来源于stack exchange,提问作者Dark Matter
相关产品推荐
相关产品推荐

