tags:

views:

72

answers:

3

Hi All,

I am trying to convert xml to csv. I am facing problem to get child node (like ProdIDT, IDV) as one line a tab delimeted txt file. Child node value is coming close without header. Please look at the below my input and XSL file.

XML

<Product>
<Record>1616200243</Record>
<Not>03</Not>
<ProductId>
<ProdIDT>02</ProdIDT>
<IDV>1616200243</IDV>
</ProductId>
<ProductId>
<ProdIDT>03</ProdIDT>
<IDV>9781616200244</IDV>
</ProductId>
<ProdFormDe>Electronic book text</ProdFormDe>
<EpTy>000</EpTy>
<NoS/>
<Title>
<TitleT>01</TitleT>
<TTx>The Sound of a Wild Snail Eating</TTx>
<Sbt>A Memoir</Sbt>
</Title>
</Product>

My XSL

<xsl:for-each select="//Product/child::*|//Product/self::*">

  <xsl:if test="$fieldNames = 'yes'">

    <xsl:if test="position() = 1 or position()&gt;1">

      <xsl:for-each select="@*">
        <xsl:value-of select="name()"/>

        <xsl:value-of select="$delimiter"/>

      </xsl:for-each>

      <xsl:for-each select="*">
        <xsl:value-of select="name()"/>

        <xsl:if test="position() != last()">
          <xsl:value-of select="$delimiter"/>
        </xsl:if>
      </xsl:for-each>
      <xsl:text>
    </xsl:text>
    </xsl:if>
  </xsl:if>
  <xsl:for-each select="@*">
    <xsl:value-of select="."/>
    <xsl:value-of select="$delimiter"/>
  </xsl:for-each>
  <xsl:for-each select="*">
    <xsl:value-of select="."/>
    <xsl:if test="position() != last()">
      <xsl:value-of select="$delimiter"/>
    </xsl:if>
  </xsl:for-each>
  <xsl:text>

Required Output

Record          Not     ProductId   ProdIDT IDV             ProductId       ProdIDT IDV             ProdFormDe      EpTy    NoS Title           TitleT  TTx     Sbt
1616200243      03                      02      1616200243                      03      9781616200244   Electronic book text            000             01      The Sound of a Wild Snail Eating        A Memoir

Thanks Byomokesh

A: 

Something like this:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
 <xsl:output method="text"/>

<xsl:template match="/">
  <xsl:for-each select="/*//*">
   <xsl:value-of select="concat(name(), '&#9;')"/>
  </xsl:for-each>
  <xsl:text>&#xA;</xsl:text>
  <xsl:for-each select="/*//*">
    <xsl:value-of select="concat(text(), '&#9;')"/>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Dimitre Novatchev
If its coming two <product> information it will come online. Enter Mark is not coming for every <product> tag.
Byomokesh
@Byomokesh: I don't understand anything of your comment. Clarify, please.
Dimitre Novatchev
<Mess><product><!-- All product information tag --></product><product><!-- All product information tag. --></product></Mess>In this case both product text is coming in one one line. Like...Record Not ProductId ProdIDT IDV 1616200243 03 02 1616200243 <!-- Another Product information should come next line -->Record Not ProductId ProdIDT IDV 4614200243 02 02 1616200243
Byomokesh
A: 

basically, you need 2 loops. One for-each Product and inside that loop there should be another for all the properties of the Product. And after each product, write out a newline character. Something like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:for-each select="//Product[position()=1]">
      <xsl:for-each select=".//*">
        <xsl:value-of select="name()" />
        <xsl:call-template name="WriteTab" />
      </xsl:for-each>
    </xsl:for-each>
    <xsl:call-template name="WriteNewLine" />

    <xsl:for-each select="//Product">
      <xsl:for-each select=".//*">
        <xsl:value-of select="text()" />
        <xsl:call-template name="WriteTab" />
      </xsl:for-each>
      <xsl:call-template name="WriteNewLine" />
    </xsl:for-each>
  </xsl:template>

  <xsl:template name ="WriteNewLine">
    <xsl:text>
</xsl:text>
  </xsl:template>

  <xsl:template name="WriteTab">
    <xsl:text>&#9;</xsl:text>
  </xsl:template>

Catch22
A: 

This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output method="text"/>
    <xsl:template match="/*">
        <xsl:apply-templates select="*[1]" mode="header"/>
        <xsl:apply-templates/>
    </xsl:template>
    <xsl:template match="*[not(*)]" mode="header">
        <xsl:value-of
         select="concat(name(),
                        substring('&#x9;&#xA;',
                                  1+boolean(following::*[1][self::Product]
                                            or not(following::*[1])),
                                  1))"/>
    </xsl:template>
    <xsl:template match="*[not(*)]">
        <xsl:value-of
         select="concat(.,
                        substring('&#x9;&#xA;',
                                  1+boolean(following::*[1][self::Product]
                                            or not(following::*[1])),
                                  1))"/>
    </xsl:template>
</xsl:stylesheet>

With this input:

<root>
    <Product>
        <Record>1616200243</Record>
        <Not>03</Not>
        <ProductId>
            <ProdIDT>02</ProdIDT>
            <IDV>1616200243</IDV>
        </ProductId>
        <ProductId>
            <ProdIDT>03</ProdIDT>
            <IDV>9781616200244</IDV>
        </ProductId>
        <ProdFormDe>Electronic book text</ProdFormDe>
        <EpTy>000</EpTy>
        <NoS/>
        <Title>
            <TitleT>01</TitleT>
            <TTx>The Sound of a Wild Snail Eating</TTx>
            <Sbt>A Memoir</Sbt>
        </Title>
    </Product>
</root>

Output:

Record  Not ProdIDT IDV ProdIDT IDV ProdFormDe  EpTy    NoS TitleT  TTx Sbt
1616200243  03  02  1616200243  03  9781616200244   Electronic book text    000     01  The Sound of a Wild Snail Eating    A Memoir
Alejandro