XSLT to convert dynamic XML to CSV and the XML nod

2019-03-05 10:48发布

问题:

Am trying to create an XSLT to convert XML to CSV. Here am placing my XML and expected output anyone have any idea how to get the below output please share me on priority.

My XML is

  <SttlmOblgtnRpt>
<RptDtls>
  <SttlmOblgtnDtls>
    <SttlmOblgtnId>A</SttlmOblgtnId>
    <FinInstrmId>
      <OthrId>
        <Id>SETTLE</Id>
        <Tp>
          <Cd>CO</Cd>
        </Tp>
      </OthrId>
    </FinInstrmId>
    <IntnddSttlmDt>
      <Dt>
        <Dt>2011-11-11</Dt>
      </Dt>
    </IntnddSttlmDt>
    <Qty>
      <Unit>11</Unit>
    </Qty>
    <SttlmAmt>
      <Amt Ccy="ZAR">20.00</Amt>
    </SttlmAmt>
    <PlcOfTrad>
      <Id>
        <Desc>SA</Desc>
      </Id>
      <Tp>
        <Cd>PR</Cd>
      </Tp>
    </PlcOfTrad>
    <Pmt>Fail</Pmt>
    <AddtlSttlmOblgtnDtls>
      <RltdSttlmOblgtnId>Debit</RltdSttlmOblgtnId>
      <Qty>
        <Unit>200</Unit>
      </Qty>
      <SttlmAmt>
        <Amt Ccy="ZAR">22.00</Amt>
      </SttlmAmt>
      <SttlmDt>2011-11-11</SttlmDt>
      <SctiesMvmntTp>INDIA</SctiesMvmntTp>
      <Pmt>MT</Pmt>
    </AddtlSttlmOblgtnDtls>
    <AddtlSttlmOblgtnDtls>
      <RltdSttlmOblgtnId>Outward</RltdSttlmOblgtnId>
      <Qty>
        <Unit>1</Unit>
      </Qty>
      <SttlmAmt>
        <Amt Ccy="ZAR">100.00</Amt>
      </SttlmAmt>
      <SttlmDt>2015-12-01</SttlmDt>
      <SctiesMvmntTp>UK</SctiesMvmntTp>
      <Pmt>EMP</Pmt>
    </AddtlSttlmOblgtnDtls>
  </SttlmOblgtnDtls>
</RptDtls>
<RptDtls>
  <SttlmOblgtnDtls>
    <SttlmOblgtnId>B</SttlmOblgtnId>
    <FinInstrmId>
      <OthrId>
        <Id>UNSETTLE</Id>
        <Tp>
          <Cd>MM</Cd>
        </Tp>
      </OthrId>
    </FinInstrmId>
    <IntnddSttlmDt>
      <Dt>
        <Dt>2012-12-12</Dt>
      </Dt>
    </IntnddSttlmDt>
    <Qty>
      <Unit>22</Unit>
    </Qty>
    <SttlmAmt>
      <Amt Ccy="ZAR">60.00</Amt>
    </SttlmAmt>
    <PlcOfTrad>
      <Id>
        <Desc>RB</Desc>
      </Id>
      <Tp>
        <Cd>IM</Cd>
      </Tp>
    </PlcOfTrad>
    <Pmt>Ok</Pmt>
    <AddtlSttlmOblgtnDtls>
      <RltdSttlmOblgtnId>Credit</RltdSttlmOblgtnId>
      <Qty>
        <Unit>100</Unit>
      </Qty>
      <SttlmAmt>
        <Amt Ccy="ZAR">66.00</Amt>
      </SttlmAmt>
      <SttlmDt>2012-12-12</SttlmDt>
      <SctiesMvmntTp>DELHI</SctiesMvmntTp>
      <Pmt>AP</Pmt>
    </AddtlSttlmOblgtnDtls>
    <AddtlSttlmOblgtnDtls>
      <RltdSttlmOblgtnId>Value</RltdSttlmOblgtnId>
      <Qty>
        <Unit>111</Unit>
      </Qty>
      <SttlmAmt>
        <Amt Ccy="ZAR">666.00</Amt>
      </SttlmAmt>
      <SttlmDt>2001-05-05</SttlmDt>
      <SctiesMvmntTp>US</SctiesMvmntTp>
      <Pmt>PASS</Pmt>
    </AddtlSttlmOblgtnDtls>
  </SttlmOblgtnDtls>
 </RptDtls>  </SttlmOblgtnRpt>

And my expected output is

SttlmOblgtnId,Pmt,Id,Cd,Dt,Unit,Amt,Desc,Cd,RltdSttlmOblgtnId,SttlmDt,SctiesMvmntTp,Pmt,Unit,Amt

A,Fail,SETTLE,CO,11/11/2011,11,20,SA,PR,Debit,11/11/2011,INDIA,MT,200,22

,,,,,,,,,Outward,12/1/2015,UK,EMP,1,100

B,Ok,UNSETTLE,MM,12/12/2012,22,60,RB,IM,Credit,12/12/2012,DELHI,AP,100,66

,,,,,,,,,Value,5/5/2001,US,PASS,111,666

Thanks,

Mahesh.

回答1:

you can use this

<xsl:template match="RptDtls">
    <xsl:for-each select="descendant::AddtlSttlmOblgtnDtls">
        <xsl:variable name="pos" select="position()"/>
        <xsl:value-of select="parent::SttlmOblgtnDtls/SttlmOblgtnId[$pos]"/><xsl:text>,</xsl:text>
        <xsl:value-of select="parent::SttlmOblgtnDtls/Pmt[$pos]"/><xsl:text>,</xsl:text>
        <xsl:value-of select="parent::SttlmOblgtnDtls/FinInstrmId[$pos]/OthrId/Id"/><xsl:text>,</xsl:text>
        <xsl:value-of select="parent::SttlmOblgtnDtls/FinInstrmId[$pos]/OthrId/Tp/Cd"/><xsl:text>,</xsl:text>
        <xsl:value-of select="replace(parent::SttlmOblgtnDtls/IntnddSttlmDt[$pos]/Dt/Dt, '([\d]{4})-0?([\d]{1,2})-0?([\d]{1,2})', '$2/$3/$1')"/><xsl:text>,</xsl:text>
        <xsl:value-of select="parent::SttlmOblgtnDtls/Qty[$pos]/Unit"/><xsl:text>,</xsl:text>
        <xsl:if test="normalize-space(parent::SttlmOblgtnDtls/SttlmAmt[$pos]/Amt) !=''">
        <xsl:value-of select="format-number(parent::SttlmOblgtnDtls/SttlmAmt[$pos]/Amt, '0')"/>
        </xsl:if><xsl:text>,</xsl:text>
        <xsl:value-of select="parent::SttlmOblgtnDtls/PlcOfTrad[$pos]/Id/Desc"/><xsl:text>,</xsl:text>
        <xsl:value-of select="parent::SttlmOblgtnDtls/PlcOfTrad[$pos]/Tp/Cd"/><xsl:text>,</xsl:text>
        <xsl:value-of select="RltdSttlmOblgtnId"/><xsl:text>,</xsl:text>
        <xsl:value-of select="replace(SttlmDt, '([\d]{4})-0?([\d]{1,2})-0?([\d]{1,2})', '$2/$3/$1')"/><xsl:text>,</xsl:text>
        <xsl:value-of select="SctiesMvmntTp"/><xsl:text>,</xsl:text>
        <xsl:value-of select="Pmt"/><xsl:text>,</xsl:text>
        <xsl:value-of select="Qty/Unit"/><xsl:text>,</xsl:text>
        <xsl:value-of select="format-number(SttlmAmt/Amt, '0')"/>
        <xsl:text>&#xa;</xsl:text>
    </xsl:for-each>
</xsl:template>

Output is

A,Fail,SETTLE,CO,11/11/2011,11,20,SA,PR,Debit,11/11/2011,INDIA,MT,200,22
,,,,,,,,,Outward,12/1/2015,UK,EMP,1,100
B,Ok,UNSETTLE,MM,12/12/2012,22,60,RB,IM,Credit,12/12/2012,DELHI,AP,100,66
,,,,,,,,,Value,5/5/2001,US,PASS,111,666


回答2:

The following stylesheet will produce the expected result (minus some formatting issues) from the given example. Whether that's the logic you want to apply in general is not clear.

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:template match="/SttlmOblgtnRpt">
    <!-- header -->
    <xsl:text>SttlmOblgtnId,Pmt,Id,Cd,Dt,Unit,Amt,Desc,Cd,RltdSttlmOblgtnId,SttlmDt,SctiesMvmntTp,Pmt,Unit,Amt&#10;</xsl:text>
    <!-- data -->
    <xsl:for-each select="RptDtls/SttlmOblgtnDtls">
        <!-- first row -->
        <xsl:value-of select="SttlmOblgtnId" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="Pmt" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="FinInstrmId/OthrId/Id" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="FinInstrmId/OthrId/Tp/Cd" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="IntnddSttlmDt/Dt/Dt" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="Qty/Unit" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="SttlmAmt/Amt" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="PlcOfTrad/Id/Desc" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="PlcOfTrad/Tp/Cd" />
        <xsl:text>,</xsl:text>
        <!-- first AddtlSttlmOblgtnDtls -->
        <xsl:value-of select="AddtlSttlmOblgtnDtls[1]/RltdSttlmOblgtnId" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="AddtlSttlmOblgtnDtls[1]/SttlmDt" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="AddtlSttlmOblgtnDtls[1]/SctiesMvmntTp" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="AddtlSttlmOblgtnDtls[1]/Pmt" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="AddtlSttlmOblgtnDtls[1]/SttlmAmt/Amt" />
        <xsl:text>&#10;</xsl:text>
        <!-- second row -->
        <xsl:text>,,,,,,,,,</xsl:text>
        <xsl:value-of select="AddtlSttlmOblgtnDtls[2]/RltdSttlmOblgtnId" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="AddtlSttlmOblgtnDtls[2]/SttlmDt" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="AddtlSttlmOblgtnDtls[2]/SctiesMvmntTp" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="AddtlSttlmOblgtnDtls[2]/Pmt" />
        <xsl:text>,</xsl:text>
        <xsl:value-of select="AddtlSttlmOblgtnDtls[2]/SttlmAmt/Amt" />
        <xsl:text>&#10;</xsl:text>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Result:

SttlmOblgtnId,Pmt,Id,Cd,Dt,Unit,Amt,Desc,Cd,RltdSttlmOblgtnId,SttlmDt,SctiesMvmntTp,Pmt,Unit,Amt
A,Fail,SETTLE,CO,2011-11-11,11,20.00,SA,PR,Debit,2011-11-11,INDIA,MT,22.00
,,,,,,,,,Outward,2015-12-01,UK,EMP,100.00
B,Ok,UNSETTLE,MM,2012-12-12,22,60.00,RB,IM,Credit,2012-12-12,DELHI,AP,66.00
,,,,,,,,,Value,2001-05-05,US,PASS,666.00


标签: csv xslt