修改XSLT实现XML转CSV时Position-Nbr列为首列
需求实现方案
需求概述
现有XML数据源及XSLT转换脚本,用于生成CSV文件。headerFieldsMap节点定义CSV表头,psPositions节点存储业务数据。需调整XSLT逻辑,确保当headerFieldsMap中包含PositionNbr节点时,其对应的表头文本“Position-Nbr”固定为CSV的第一列。
原XML数据源
<root> <headerFieldsMap> <BusinessUnit>Business Unit Code</BusinessUnit> <CompanyName>Business Unit Desct</CompanyName> <DeptDescr>Department Description</DeptDescr> <DeptId>Department</DeptId> <DescrShort>Posting Job Title</DescrShort> <Description>Working Position Description</Description> <JobFamily>Category</JobFamily> <PositionNbr>Position-Nbr</PositionNbr> <StdHoursFreq>Standard hours Frequency</StdHoursFreq> <TotalWorkingHours>Standard Hours</TotalWorkingHours> </headerFieldsMap> <psPositions> <position> <LocationPostal>06511</LocationPostal> <ConfidentialFlag>N</ConfidentialFlag> <DeptDescr>New Haven EMU Shop</DeptDescr> <Description>Carman E Rate</Description> <RegTemp>R</RegTemp> <SalAdminPlan>TWUR</SalAdminPlan> <JobCodeSetid>SHARE</JobCodeSetid> <LocationCountry>US</LocationCountry> <Remote>N</Remote> <Step>0</Step> <SalaryRangeTo>0</SalaryRangeTo> <PositionNbr>01000333</PositionNbr> <SalaryRangeFrom>0</SalaryRangeFrom> <EffStatus>A</EffStatus> <FullPartTime>F</FullPartTime> <PositionStatus>Approved</PositionStatus> <LocationSetId>SHARE</LocationSetId> <CompanyName>Metro-North Railroad</CompanyName> <RemainingHeadCount>0</RemainingHeadCount> <PayFrequency>H</PayFrequency> <JobCode>26448E</JobCode> <RegRegion>USA</RegRegion> <Shift>2</Shift> <ReportsToPos>01000474</ReportsToPos> <DeptIdSetId>MNCRR</DeptIdSetId> <TotalWorkingHours>40</TotalWorkingHours> <DescrShort>Carman E R</DescrShort> <StdHoursFreq>W</StdHoursFreq> <LocationCode>NEW HAVEN</LocationCode> <Effdt>2023-02-21</Effdt> <LocationDescr>98 Union Street</LocationDescr> <LocationCity>New Haven</LocationCity> <Grade>004</Grade> <JobFamily>Transportation Operations</JobFamily> <DeptId>44302</DeptId> <LastUpdDtTm>2023-02-21T19:12:05Z</LastUpdDtTm> <LocationRegion>CT</LocationRegion> <ReportsToEmail>Burns@mnr.org</ReportsToEmail> <PayCurrency>USD</PayCurrency> <MaxHeadCount>1</MaxHeadCount> <BusinessUnit>MNCRR</BusinessUnit> <JobFamilyCode>TRNOPS</JobFamilyCode> <CompanyCode>MNR</CompanyCode> <CurrHeadCount>1</CurrHeadCount> </position> </psPositions> </root>
修改后的XSLT脚本
<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:req="http://peoplesoft.com/requestResponse" xmlns:csl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8"/> <xsl:variable name="delimiter" select="','"/> <!-- 定义目标字段变量,方便后续统一引用 --> <xsl:variable name="targetField" select="'PositionNbr'"/> <xsl:template match="/root"> <!-- 表头行处理 --> <!-- 优先输出Position-Nbr表头(仅当存在时) --> <xsl:if test="headerFieldsMap/*[local-name()=$targetField]"> <xsl:value-of select="headerFieldsMap/*[local-name()=$targetField]"/> <!-- 若还有其他字段,添加分隔符 --> <xsl:if test="count(headerFieldsMap/*) > 1"> <xsl:value-of select="$delimiter"/> </xsl:if> </xsl:if> <!-- 输出剩余表头(排除PositionNbr) --> <xsl:for-each select="headerFieldsMap/*[local-name()!=$targetField]"> <xsl:value-of select="."/> <xsl:if test="position() != last()"> <xsl:value-of select="$delimiter"/> </xsl:if> </xsl:for-each> <xsl:text>
</xsl:text> <!-- 数据行处理 --> <xsl:for-each select="psPositions/position"> <xsl:variable name="row" select="."/> <!-- 优先输出PositionNbr数据(仅当表头包含该字段时) --> <xsl:if test="/root/headerFieldsMap/*[local-name()=$targetField]"> <xsl:value-of select="$row/*[local-name()=$targetField]"/> <!-- 若还有其他字段,添加分隔符 --> <xsl:if test="count(/root/headerFieldsMap/*) > 1"> <xsl:value-of select="$delimiter"/> </xsl:if> </xsl:if> <!-- 输出剩余数据(排除PositionNbr),保留原有转换逻辑 --> <xsl:for-each select="/root/headerFieldsMap/*[local-name()!=$targetField]"> <xsl:variable name="fieldName" select="local-name()"/> <xsl:choose> <xsl:when test="$row/*[local-name()=$fieldName] = 'W' and $fieldName = 'StdHoursFreq'"> <xsl:text>Weekly</xsl:text> </xsl:when> <xsl:when test="$row/*[local-name()=$fieldName] = 'B' and $fieldName = 'StdHoursFreq'"> <xsl:text>Bi-Weekly</xsl:text> </xsl:when> <xsl:when test="$row/*[local-name()=$fieldName] = 'M' and $fieldName = 'StdHoursFreq'"> <xsl:text>Monthly</xsl:text> </xsl:when> <xsl:when test="$fieldName = 'DescrShort'"> <xsl:value-of select="$row/*[local-name()='Description']"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$row/*[local-name()=$fieldName]"/> </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>
修改说明
- 表头逻辑调整:先判断
PositionNbr是否存在,存在则优先输出其表头,再遍历输出剩余表头字段 - 数据行逻辑同步:对应表头顺序,先输出
PositionNbr的数据,再按剩余表头顺序输出对应数据 - 兼容性保留:如果
headerFieldsMap中没有PositionNbr节点,转换逻辑自动退化为原有行为,不影响其他场景
转换结果示例
Position-Nbr,Business Unit Code,Business Unit Desct,Department Description,Department,Posting Job Title,Working Position Description,Category,Standard hours Frequency,Standard Hours 01000333,MNCRR,Metro-North Railroad,New Haven EMU Shop,44302,Carman E Rate,Carman E Rate,Transportation Operations,Weekly,40
内容的提问来源于stack exchange,提问作者Dark Matter
相关产品推荐
相关产品推荐

