我需要写一个xslt转换xml到csv与特定的数据

j8yoct9x  于 2023-03-05  发布在  其他
关注(0)|答案(2)|浏览(118)

我正在尝试写一个xslt,它从xml创建一个csv。我需要创建一个头字段Map,使头匹配数据。下面是一个xml示例

<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>

csv或输出应如下所示

Business Unit Code,Business Unit Desct,Department Description,Department,Posting Job Title,Working Position Description,Category,Position-Nbr,Standard hours Frequency,Standard Hours
MNCRR,Metro-North Railroad,New Haven EMU Shop,44302,Carman E R,Carman E Rate,Transportation Operations,01000333,W,40
MTAHQ,MTA Headquarters,Division of Management /Budget,400300,SR FINANCI,Sr Financial Analyst - Budgets,Finance/Accounting,01055644,W,37.5

请注意,数据中只有字段中提到的字段的值。中的字段可能会有所不同,只能有2个字段,数据应相应显示。
我的当前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="','"/>

  <xsl:template match="/">
    <!-- Header row -->
    <xsl:for-each select="root/headerFieldsMap/*">
      <xsl:value-of select="."/>
      <xsl:if test="position() != last()">
        <xsl:value-of select="$delimiter"/>
      </xsl:if>
    </xsl:for-each>
    <xsl:text>&#10;</xsl:text>

    <!-- Data rows -->
    <xsl:for-each select="root/psPositions/position">
      <xsl:for-each select="*">
        <xsl:variable name="fieldName" select="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="$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>&#10;</xsl:text>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

但是这个输出了xml中的所有数据。我只需要头中提到的数据。XSLT标准:1.0
上面的xslt生成的输出如下所示,它不应该包含不在标题中的字段的数据,比如“Burns@mnr.org“不应该出现,因为“ReportsToEmail”不在标题中。

Business Unit Code,Business Unit Desct,Department Description,Department,Posting Job Title,Working Position Description,Category,Position-Nbr,Standard hours Frequency,Standard Hours
06511,N,New Haven EMU Shop,Carman E Rate,R,TWUR,SHARE,US,N,0,0,01000333,0,A,F,Approved,SHARE,Metro-North Railroad,0,H,26448E,USA,2,01000474,MNCRR,40,Carman E R,Weekly,NEW HAVEN,2023-02-21,98 Union Street,New Haven,004,Transportation Operations,44302,2023-02-21T19:12:05Z,CT,Burns@mnr.org,USD,1,MNCRR,TRNOPS,MNR,1
10004,Y,Division of Management /Budget,Sr Financial Analyst - Budgets,R,HAY0,SHARE,US,N,0,0,01055644,0,A,F,Approved,SHARE,MTA Headquarters,1,B,1287,USA,1,01005823,MTAHQ,37.5,SR FINANCI,Weekly,2 BROADWAY,2023-02-21,2 Broadway,New York,438,Finance/Accounting,400300,2023-02-21T12:57:45Z,NY,USD,1,MTAHQ,FINANC,MTA,0
xj3cbfub

xj3cbfub1#

请尝试以下XSLT。

    • XSLT格式**
<?xml version="1.0"?>
<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="','"/>

    <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 $row/*[local-name()='StdHoursFreq']">
                        <xsl:text>Weekly</xsl:text>
                    </xsl:when>
                    <xsl:when test="$fieldName = 'DescrShort'">
                        <xsl:value-of select="$row/*[local-name()='LocationPostal']"/>
                    </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>
20jt8wwn

20jt8wwn2#

我只需要标题中提到的数据
试着按照以下思路来做:

    • XSLT 1.0版本**
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:key name="row-data" match="position/*" use="concat(name(), generate-id(..))" />

<xsl:template match="/root">
    <xsl:variable name="cols" select="headerFieldsMap/*"/>
    <!-- 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-id" select="generate-id()"/>
        <xsl:for-each select="$cols">
            <xsl:value-of select="key('row-data', concat(name(), $row-id))"/>
            <xsl:if test="position()!=last()">,</xsl:if>
        </xsl:for-each>
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

注意,从输入XML获得的结果与显示的结果有很大不同,但是样式表符合问题中的逻辑(至少我是这样理解的)。
要将W更改为Weekly,可以执行以下操作:

<xsl:for-each select="$cols">
            <xsl:variable name="value" select="key('row-data', concat(name(), $row-id))" />
            <xsl:choose>
                <xsl:when test="name() = 'StdHoursFreq' and $value = 'W'">Weekly</xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="$value"/>
                </xsl:otherwise>
            </xsl:choose>
            <xsl:if test="position()!=last()">,</xsl:if>
        </xsl:for-each>

相关问题