使用过滤器将XML转换为CSV



我有一个xml和一个将xml转换为csv的XSLT。这里headerFieldsMap是csv的头部,position是数据。XML版本为1.0我需要做出改变,使xslt使标题PositionNbr如果存在应该始终是csv的第一列。目前"业务单位代码";将作为CSV中的第一列,但我想要"Position-Nbr"如果它存在于。这是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:template match="/root">
<!-- Header row -->
<xsl:for-each select="headerFieldsMap/*">
<xsl:value-of select="."/>
<xsl:if test="position() != last()">
<xsl:value-of select="$delimiter"/>
</xsl:if>
</xsl:for-each>
<xsl:text>&#xA;</xsl:text>
<!-- Data rows -->
<xsl:for-each select="psPositions/position">
<xsl:variable name="row" select="."/>
<xsl:for-each select="/root/headerFieldsMap/*">
<xsl:variable name="fieldName" select="local-name()"/>
<xsl:variable name="fieldValue" select="."/>
<!-- If the field value is StdHoursFreq and it's equal to "W", replace it with "Weekly" -->
<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>&#xA;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

你可以这样看:

XSLT 1.0 (+ EXSLT节点集()函数)

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="text" encoding="UTF-8"/>
<xsl:template match="/root">
<xsl:variable name="cols-rtf">
<xsl:for-each select="headerFieldsMap/*">
<xsl:sort select="number(name()='PositionNbr')" data-type="number" order="descending"/>
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="cols" select="exsl:node-set($cols-rtf)/*"/>
<!-- header row-->
<xsl:for-each select="$cols">
<xsl:value-of select="."/>
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
<xsl:text>&#10;</xsl:text>
<!-- data rows-->
<xsl:for-each select="psPositions/position">
<xsl:variable name="row" select="."/>
<xsl:for-each select="$cols">
<xsl:value-of select="$row/*[name()=name(current())]"/>
<xsl:if test="position()!=last()">,</xsl:if>
</xsl:for-each>
<xsl:text>&#10;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

更有效的方法是使用查找行数据,如我对您上一个问题的回答所示。但是,由于这里的列名源是一个独立变量,因此需要在调用键之前将上下文切换回XML源。

注:我忽略了XSLT的xsl:choose部分,它与问题无关。

最新更新