Nirjal Khadka
Nirjal Khadka

Reputation: 31

Creating an xsl converting xml with headers and footers for to another xml with xslt transformation,

I am a newbie in XSLT, I have an XML converted from csv file looks like below with Open and Close rows distict by text, type rows and value. They all come in with same record tags, with distinction only in the string values itself

<?xml version="1.0" encoding="utf-8"?>
<Items>
<Row>
  <Transaction>Open</Transaction>
</Row>
<Row>
  <Transaction>Type plus</Transaction>
</Row>
<Row>
  <Transaction>A</Transaction>
</Row>
<Row>
  <Transaction>B</Transaction>
</Row>    
<Row>
  <Transaction>Close</Transaction>
</Row>
<Row>
  <Transaction>Open</Transaction>
</Row>
<Row>
  <Transaction>Type minus</Transaction>
</Row>
<Row>
  <Transaction>C</Transaction>
</Row>
<Row>
  <Transaction>D</Transaction>
</Row>    
<Row>
  <Transaction>Close</Transaction>
</Row>
...
...
...
...
...   
</Items>

I want the result to look as the following.I tried using a variable to store the using variable "Type" for storing plus or minus, but seems like I can't update the variable. Can anyone create an xsl which can do the transformation to the following.

<?xml version="1.0" encoding="utf-8"?>
<result>
<message>
    <to>plus</to>
    <from>A</from>
</message>
<message>
    <to>plus</to>
    <from>B</from>
</message>
<message>
    <to>minus</to>
    <from>C</from>
</message>
<message>
    <to>minus</to>
    <from>D</from>
</message>
...
...
...
</result>

Upvotes: 0

Views: 718

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116993

The example is rather ambiguous; what we need here is some clear rules.

If we assume that in each group of Rows starting with <Transaction>Open</Transaction>, the second Row contains the type and the last one closes the group, we can do:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="grp" match="Row[not(Transaction='Open')]" use="generate-id(preceding-sibling::Row[Transaction='Open'][1])" />

<xsl:template match="Items">
    <result>
        <xsl:for-each select="Row[Transaction='Open']">
            <xsl:variable name="group" select="key('grp', generate-id())" />
            <xsl:variable name="type" select="substring-after($group[1]/Transaction, 'Type ')" />
            <xsl:for-each select="$group[position() != 1 and position() != last()]">            
                <message>
                    <to>
                        <xsl:value-of select="$type"/>
                    </to>
                    <from>
                        <xsl:value-of select="Transaction"/>
                    </from>
                </message>
            </xsl:for-each>
        </xsl:for-each>
    </result>
</xsl:template>

</xsl:stylesheet>

to obtain:

<?xml version="1.0" encoding="UTF-8"?>
<result>
  <message>
    <to>plus</to>
    <from>A</from>
  </message>
  <message>
    <to>plus</to>
    <from>B</from>
  </message>
  <message>
    <to>minus</to>
    <from>C</from>
  </message>
  <message>
    <to>minus</to>
    <from>D</from>
  </message>
</result>

Upvotes: 1

Related Questions