XSLT combine multiple list from one file to table - xslt

I need help with merging several tables of one file into one output.
The files that I get processed perfectly according to the XSLT schema that is listed below. But today I received an interesting file that was not processed as I wanted.
source file
<?xml version="1.0" encoding="utf-8"?>
<extdata user="test">
<scheme name="Order">
<data>
<s>
<d name="CashOrder">
<f name="ActionDate" type="Date" />
<f name="AddressId" type="String" />
<f name="CompanyId" type="String" />
</d>
</s>
<o>
<d name="CashOrder">
<r>
<f>2022-01-24T00:00:00</f>
<f>10234</f>
<f>10234</f>
</r>
<r>
<f>2022-01-24T00:00:00</f>
<f>52817</f>
<f>52817</f>
</r>
<r>
<f>2022-01-24T00:00:00</f>
<f>58259</f>
<f>58259</f>
</r>
</d>
</o>
</data>
<data>
<s>
<d name="OrderOption">
<f name="OrderDate" type="Date" />
<f name="OrderNumber" type="String" />
</d>
</s>
<o>
<d name="OrderOption">
<r>
<f>2022-01-24T00:00:00</f>
<f>WE30395.c17639</f>
</r>
<r>
<f>2022-01-24T00:00:00</f>
<f>WE30395.c17639</f>
</r>
<r>
<f>2022-01-24T00:00:00</f>
<f>WE30395.c17639</f>
</r>
</d>
</o>
</data>
</scheme>
</extdata>
my XSLT (here they helped me with writing.there was a problem with the recursive processing of the hierarchy)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/extdata/scheme">
<ValueTable xmlns="http://v8.1c.ru/8.1/data/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:for-each select="data/s/d/f | data/s/d/d/f">
<column>
<Name xsi:type="xs:string">
<xsl:value-of select="#name" />
</Name>
<ValueType>
<xsl:if test="#type= 'String'">
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</xsl:if>
<xsl:if test="#type= 'Date'">
<Type>xs:dateTime</Type>
<DateQualifiers>
<DateFractions>DateTime</DateFractions>
</DateQualifiers>
</xsl:if>
<xsl:if test="#type= 'Decimal' or #type= 'Currency'">
<Type>xs:decimal</Type>
<NumberQualifiers>
<Digits>20</Digits>
<FractionDigits>4</FractionDigits>
<AllowedSign>Any</AllowedSign>
</NumberQualifiers>
</xsl:if>
<xsl:if test="#type= 'Integer'">
<Type>xs:decimal</Type>
<NumberQualifiers>
<Digits>20</Digits>
<FractionDigits>0</FractionDigits>
<AllowedSign>Any</AllowedSign>
</NumberQualifiers>
</xsl:if>
</ValueType>
</column>
</xsl:for-each>
<xsl:for-each select="data/o/d/r">
<row>
<xsl:for-each select=".//f">
<Value>
<xsl:value-of select="." />
</Value>
</xsl:for-each>
</row>
</xsl:for-each>
</ValueTable>
</xsl:template>
</xsl:stylesheet>
output now
<ValueTable xmlns="http://v8.1c.ru/8.1/data/core"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<column>
<Name xsi:type="xs:string">ActionDate</Name>
<ValueType>
<Type>xs:dateTime</Type>
<DateQualifiers>
<DateFractions>DateTime</DateFractions>
</DateQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">AddressId</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">CompanyId</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">OrderDate</Name>
<ValueType>
<Type>xs:dateTime</Type>
<DateQualifiers>
<DateFractions>DateTime</DateFractions>
</DateQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">OrderNumber</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<row>
<Value>2022-01-24T00:00:00</Value>
<Value>10234</Value>
<Value>10234</Value>
</row>
<row>
<Value>2022-01-24T00:00:00</Value>
<Value>52817</Value>
<Value>52817</Value>
</row>
<row>
<Value>2022-01-24T00:00:00</Value>
<Value>58259</Value>
<Value>58259</Value>
</row>
<row>
<Value>2022-01-24T00:00:00</Value>
<Value>WE30395.c17639</Value>
</row>
<row>
<Value>2022-01-24T00:00:00</Value>
<Value>WE30395.c17639</Value>
</row>
<row>
<Value>2022-01-24T00:00:00</Value>
<Value>WE30395.c17639</Value>
</row>
</ValueTable>
need
<ValueTable xmlns="http://v8.1c.ru/8.1/data/core"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<column>
<Name xsi:type="xs:string">ActionDate</Name>
<ValueType>
<Type>xs:dateTime</Type>
<DateQualifiers>
<DateFractions>DateTime</DateFractions>
</DateQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">AddressId</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">CompanyId</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">OrderDate</Name>
<ValueType>
<Type>xs:dateTime</Type>
<DateQualifiers>
<DateFractions>DateTime</DateFractions>
</DateQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">OrderNumber</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<row>
<Value>2022-01-24T00:00:00</Value>
<Value>10234</Value>
<Value>10234</Value>
<Value>2022-01-24T00:00:00</Value>
<Value>WE30395.c17639</Value>
</row>
<row>
<Value>2022-01-24T00:00:00</Value>
<Value>52817</Value>
<Value>52817</Value>
<Value>2022-01-24T00:00:00</Value>
<Value>WE30395.c17639</Value>
</row>
<row>
<Value>2022-01-24T00:00:00</Value>
<Value>58259</Value>
<Value>58259</Value>
<Value>2022-01-24T00:00:00</Value>
<Value>WE30395.c17639</Value>
</row>
</ValueTable>
Briefly, the structure can be described as follows
I mean this is how I got it
<table>
<header>
<column1>
<column2>
<column3>
<column4>
<column5>
<header>
<row>
value1
value2
value3
</row>
<row>
value4
value5
</row>
</table>
but it should be like this
<table>
<header>
<column1>
<column2>
<column3>
<column4>
<column5>
</header>
<row>
value1
value2
value3
value4
value5
</row>
</table>

The example is rather confusing because many values are identical and it's hard to see what goes where. It's also not clear if there can be more data elements and if so, what should the result be then.
AFAICT, this produces the expected result for the given example. For clarity, I have omitted the header part, which seems to be working fine.
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes" />
<xsl:template match="/extdata/scheme">
<ValueTable xmlns="http://v8.1c.ru/8.1/data/core" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- header -->
<!-- data -->
<xsl:for-each select="data[1]/o/d/r">
<row>
<xsl:variable name="i" select="position()"/>
<xsl:for-each select="//data/o/d/r[$i]/f">
<Value>
<xsl:value-of select="." />
</Value>
</xsl:for-each>
</row>
</xsl:for-each>
</ValueTable>
</xsl:template>
</xsl:stylesheet>

Related

XSLT group every nth item in to new group

I have done few XSLT in the past, but I am facing challenge in this.
I am working with PLC tag, for each tag i am getting three rowset node, so after every three Rowset i need to create new "Row" group.
Updated with XSLT
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<Rowsets >
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<WC_ID>0001</WC_ID>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<Tag1_Good>6817</Tag1_Good>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<Tag1_Bad>0</Tag1_Bad>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<WC_ID>0002</WC_ID>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<Tag2_Good>6800</Tag2_Good>
</Row>
</Rowset>
<Rowset>
<Row>
<DateTime>2021-07-05T07:33:38</DateTime>
<Tag2_Bad>0</Tag2_Bad>
</Row>
</Rowset>
</Rowsets>
Expected output:
<?xml version="1.0" encoding="UTF-8"?>
<Rowset>
<Row>
<WC_ID>0001</WC_ID>
<Tag1_Good>6817</Tag1_Good>
<Tag1_Bad>0</Tag1_Bad>
</Row>
<Row>
<WC_ID>0002</WC_ID>
<Tag1_Good>6800</Tag1_Good>
<Tag1_Bad>0</Tag1_Bad>
</Row>
</Rowset>
My XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<Rowsets >
<xsl:variable name="batchSize" select="3"/>
<Rowset>
<xsl:for-each select="/Rowsets/Rowset[position() mod $batchSize >= 0]"
<Row>
<xsl:value-of select="Row/*[2]" />
</Row>
</xsl:for-each>
</Rowset>
</Rowsets>
</xsl:template>
</xsl:stylesheet>
I am not able to make this into a new group
Use this:
<Rowsets>
<xsl:variable name="batchSize" select="3"/>
<Rowset>
<xsl:for-each select="/Rowsets/Rowset">
<xsl:variable name="pos" select="position()"/>
<xsl:if test="$pos mod $batchSize = 0">
<Row>
<WC_ID>
<xsl:value-of select="/Rowsets/Rowset[$pos - 2]/Row/*[2]"/>
</WC_ID>
<Tag1_Good>
<xsl:value-of select="/Rowsets/Rowset[$pos - 1]/Row/*[2]"/>
</Tag1_Good>
<Tag1_Bad>
<xsl:value-of select="/Rowsets/Rowset[$pos]/Row/*[2]"/>
</Tag1_Bad>
</Row>
</xsl:if>
</xsl:for-each>
</Rowset>
</Rowsets>

Removing comma from number format with unique XSLT coding

With the example below, the XSLT is doing a few things, it is grouping by column 1 and column2, if it is the same, then it will group the column 3 amount. As well, within the PayAmount tags, it is reversing negative (-) number into a positive and vice versa. What I am having troubles with is writing logic to remove the comma (,) from column 3 in the output.
Below is my XSLT Code
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="data">
<xsl:for-each select="row[generate-id(.) = generate-id(key(''rows'', concat(column1, ''||'', column2)))]">
</Record>
<Detail>
<Amount>
<xsl:variable name="mySum">
<xsl:value-of select="sum(key(''rows'', concat(column1, ''||'', column2))/column3)" />
</xsl:variable>
<xsl:value-of select="translate(($mySum * ($mySum >= 0) - $mySum * not($mySum >= 0)),'','','''')" />
</Amount>
</Detail>
</Record>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I have tried the following logic, but the comma remains in the output:
- <xsl:value-of select="translate(($mySum * ($mySum >= 0) - $mySum * not($mySum >= 0)),'','', '''')" />
- <xsl:value-of select="format-number($mySum * ($mySum >= 0) - $mySum * not($mySum >= 0),'#,##0.00')" />
- <xsl:value-of select="translate(sum(key(''rows'', concat(column1, ''||'', column2))/column3),'','','''')" />
Below is a sample data in XML:
<data>
<row>
<column1>200040</column1>
<column2>Auto</column2>
<column3>-500.00</column3>
</row>
<row>
<column1>200040</column1>
<column2>Auto</column2>
<column3>-5,000.00</column3>
</row>
<row>
<column1>200040</column1>
<column2>Auto</column2>
<column3>-1,000.00</column3>
</row>
<row>
<column1>200040</column1>
<column2>Auto</column2>
<column3>300.00</column3>
</row>
<row>
<column1>200040</column1>
<column2>Auto</column2>
<column3>-4,000.00</column3>
</row>
<row>
<column1>200041</column1>
<column2>Bike</column2>
<column3>-1,700.00</column3>
</row>
<row>
<column1>200041</column1>
<column2>Bike</column2>
<column3>-1,000.00</column3>
</row>
<row>
<column1>200041</column1>
<column2>Bike</column2>
<column3>800.00</column3>
</row>
<row>
<column1>200045</column1>
<column2>Bus</column2>
<column3>200.00</column3>
</row>
<row>
<column1>200045</column1>
<column2>Bus</column2>
<column3>-10,000.00</column3>
</row>
<row>
<column1>200045</column1>
<column2>Bus</column2>
<column3>5,000.00</column3>
</row>
</data>
The output I would like to achieve after running the XSLT is
200040 | Auto | 10200.00
200041 | Bike | 1900.00
200045 | Bus | 4800.00
Any help would be greatly appreciated!
A value that contains a comma is not a number and cannot be summed. You need to remove the commas before you attempt to sum the values.
Here's a simplified example:
XSLT 1.0 + EXSLT node-set()
<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="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:key name="a" match="amount" use="#key"/>
<xsl:template match="data">
<!-- first pass: convert amounts to numbers -->
<xsl:variable name="amounts">
<xsl:for-each select="row">
<amount key="{concat(column1, '|', column2)}">
<xsl:value-of select="translate(column3, ',', '')"/>
</amount>
</xsl:for-each>
</xsl:variable>
<!-- output -->
<Output>
<xsl:for-each select="exsl:node-set($amounts)/amount[generate-id() = generate-id(key('a', #key))]">
<Record>
<Detail1>
<xsl:value-of select="substring-before(#key, '|')"/>
</Detail1>
<Detail2>
<xsl:value-of select="substring-after(#key, '|')"/>
</Detail2>
<xsl:variable name="sum" select="sum(key('a', #key))"/>
<Amount>
<xsl:value-of select="format-number($sum, '0.00')"/>
</Amount>
</Record>
</xsl:for-each>
</Output>
</xsl:template>
</xsl:stylesheet>
Applied to your input example, this will produce:
Result
<?xml version="1.0" encoding="UTF-8"?>
<Output>
<Record>
<Detail1>200040</Detail1>
<Detail2>Auto</Detail2>
<Amount>-10200.00</Amount>
</Record>
<Record>
<Detail1>200041</Detail1>
<Detail2>Bike</Detail2>
<Amount>-1900.00</Amount>
</Record>
<Record>
<Detail1>200045</Detail1>
<Detail2>Bus</Detail2>
<Amount>-4800.00</Amount>
</Record>
</Output>
To reverse negative amounts to positive (and vice versa), you could simply change:
<xsl:value-of select="format-number($sum, '0.00')"/>
to:
<xsl:value-of select="format-number(-$sum, '0.00')"/>

XSLT grouping multiple levels [duplicate]

I'm trying to group the input below by the destination and assortment values using muenchian-grouping which is new for me so I'm not sure how to do it properly. The input files will be much larger than this so performance is important.
<?xml version="1.0"?>
<ns0:Data xmlns:ns0="http://BizTalk_Projects.input">
<transports>
<destination>destination 1</destination>
<assortment>Volvo_GA961</assortment>
<quantity>10</quantity>
</transports>
<transports>
<destination>destination 1</destination>
<assortment>Volvo_GA961</assortment>
<quantity>15</quantity>
</transports>
<transports>
<destination>destination 1</destination>
<assortment>Volvo_GA969</assortment>
<quantity>15</quantity>
</transports>
<transports>
<destination>destination 1</destination>
<assortment>Volvo_GA972</assortment>
<quantity>5</quantity>
</transports>
<transports>
<destination>destination 1</destination>
<assortment>Volvo_SA980</assortment>
<quantity>20</quantity>
</transports>
<transports>
<destination>destination 2</destination>
<assortment>Volvo_GA960</assortment>
<quantity>10</quantity>
</transports>
<transports>
<destination>destination 1</destination>
<assortment>Nissan_GA963</assortment>
<quantity>5</quantity>
</transports>
<transports>
<destination>destination 1</destination>
<assortment>Nissan_GA963</assortment>
<quantity>5</quantity>
</transports>
</ns0:Data>
Expected output:
<?xml version="1.0" encoding="UTF-8"?>
<ns0:Destinations xmlns:ns0="http://BizTalk_Projects.output">
<Destination>
<name>destination 1</name>
<assortment>
<name>Volvo_GA</name>
<row>
<type>sumPerAssortment</type>
<id>961</id>
<totalQuantity>25</totalQuantity>
<region>1</region>
</row>
<row>
<type>sumPerAssortment</type>
<id>969</id>
<totalQuantity>15</totalQuantity>
<region>1</region>
</row>
<row>
<type>sumPerAssortment</type>
<id>972</id>
<totalQuantity>5</totalQuantity>
<region>2</region>
</row>
<row>
<type>sumPerRegion</type>
<id />
<totalQuantity>40</totalQuantity>
<region>1</region>
</row>
<row>
<type>sumPerRegion</type>
<id />
<totalQuantity>5</totalQuantity>
<region>2</region>
</row>
<row>
<type>totalSum</type>
<id />
<totalQuantity>45</totalQuantity>
<region />
</row>
</assortment>
<assortment>
<name>Volvo_SA</name>
<row>
<type>sumPerAssortment</type>
<id>980</id>
<totalQuantity>20</totalQuantity>
<region>3</region>
</row>
<row>
<type>sumPerRegion</type>
<id />
<totalQuantity>20</totalQuantity>
<region>3</region>
</row>
<row>
<type>totalSum</type>
<id />
<totalQuantity>20</totalQuantity>
<region />
</row>
</assortment>
<assortment>
<name>Nissan_GA</name>
<row>
<type>sumPerAssortment</type>
<id>963</id>
<totalQuantity>10</totalQuantity>
<region>1</region>
</row>
<row>
<type>sumPerRegion</type>
<id />
<totalQuantity>10</totalQuantity>
<region>1</region>
</row>
<row>
<type>totalSum</type>
<id />
<totalQuantity>10</totalQuantity>
<region />
</row>
</assortment>
</Destination>
<Destination>
<name>destination 2</name>
<assortment>
<name>Volvo_GA</name>
<row>
<type>sumPerAssortment</type>
<id>960</id>
<totalQuantity>10</totalQuantity>
<region>1</region>
</row>
<row>
<type>sumPerRegion</type>
<id />
<totalQuantity>10</totalQuantity>
<region>1</region>
</row>
<row>
<type>totalSum</type>
<id />
<totalQuantity>10</totalQuantity>
<region />
</row>
</assortment>
</Destination>
</ns0:Destinations>
Note:
assortment number starting with 96 = region 1
assortment number starting with 97 = region 2
assortment number starting with 98 = region 3
Start of my XSLT:
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:var="http://schemas.microsoft.com/BizTalk/2003/var"
exclude-result-prefixes="msxsl var s0"
version="1.0"
xmlns:s0="http://BizTalk_Projects.input"
xmlns:ns0="http://BizTalk_Projects.output">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
<xsl:key name="destinationKey" match="transports" use="destination"/>
<xsl:template match="/">
<xsl:apply-templates select="/s0:Data" />
</xsl:template>
<xsl:template match="/s0:Data">
<ns0:Destinations>
<xsl:for-each select="transports[count(. | key('destinationKey',destination)[1]) = 1]">
<Destination>
<name>
<xsl:value-of select="destination/text()" />
</name>
<xsl:for-each select="key('destinationKey',destination)">
<assortment>
<name>
<xsl:value-of select="substring(assortment/text(),1,string-length(assortment)-3)" />
</name>
</assortment>
</xsl:for-each>
</Destination>
</xsl:for-each>
</ns0:Destinations>
</xsl:template>
</xsl:stylesheet>
With this code, I'm getting this output (duplicate rows, but correct assortments for each destination);
<ns0:Destinations xmlns:ns0="http://BizTalk_Projects.output">
<Destination>
<name>destination 1</name>
<assortment>
<name>Volvo_GA</name>
</assortment>
<assortment>
<name>Volvo_GA</name>
</assortment>
<assortment>
<name>Volvo_GA</name>
</assortment>
<assortment>
<name>Volvo_GA</name>
</assortment>
<assortment>
<name>Volvo_SA</name>
</assortment>
<assortment>
<name>Nissan_GA</name>
</assortment>
<assortment>
<name>Nissan_GA</name>
</assortment>
</Destination>
<Destination>
<name>destination 2</name>
<assortment>
<name>Volvo_GA</name>
</assortment>
</Destination>
</ns0:Destinations>
Any suggestions on how I can solve this? Help is very appreciated!
It's difficult to see how exactly the output relates to the input. Try this as your starting point:
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="transports-by-destination" match="transports" use="destination" />
<xsl:key name="transports-by-assortment" match="transports" use="concat(destination, '|', assortment)" />
<xsl:template match="/*">
<xsl:copy>
<!-- for each unique destination -->
<xsl:for-each select="transports[count(. | key('transports-by-destination', destination)[1]) = 1]">
<Destination>
<name>
<xsl:value-of select="destination"/>
</name>
<xsl:variable name="group" select="key('transports-by-destination', destination)" />
<!-- for each unique assortment in this destination -->
<xsl:for-each select="$group[count(. | key('transports-by-assortment', concat(destination, '|', assortment))[1]) = 1]">
<assortment>
<name>
<xsl:value-of select="assortment"/>
</name>
<!-- process this subgroup -->
<xsl:for-each select="key('transports-by-assortment', concat(destination, '|', assortment))" >
<row>
<!-- not sure what goes in here -->
<totalQuantity>
<xsl:value-of select="quantity"/>
</totalQuantity>
</row>
</xsl:for-each>
</assortment>
</xsl:for-each>
</Destination>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

how to combine elements in multiple rows using a repeating element

Below is my Input xml and I want to use xslt 1.0 to transform into below specified xml.
Element ref needs to be used as key to merge and create the array in the output
Input xml :
<Input>
<row>
<Name>ABC</Name>
<Ref>12345</Ref>
<Status>O</Status>
<Currency>USD</Currency>
<Date>2016-05-16</Date>
</row>
<row>
<Name>ABC</Name>
<Ref>12345</Ref>
<Status>O</Status>
<Currency>AUD</Currency>
<Date>2016-05-01</Date>
</row>
<row>
<Name>XYZ</Name>
<Ref>54321</Ref>
<Status>O</Status>
<Currency>AUD</Currency>
<Date>2016-03-01</Date>
</row>
<row>
<Name>XYZ</Name>
<Ref>54321</Ref>
<Status>O</Status>
<Currency>USD</Currency>
<Date>2016-05-01</Date>
</row>
</Input>
Output Xml: using the ref element in the request the there will be only two row elements in the output xml, but the values that are different are clubbed in a another sub node.
<Output>
<row>
<Name>ABC</Name>
<Ref>12345</Ref>
<Status>O</Status>
<Details>
<Detail>
<Currency>USD</Currency>
<Date>2016-05-16</Date>
</Detail>
<Detail>
<Currency>AUD</Currency>
<Date>2016-05-01</Date>
</Detail>
</Details>
</row>
<row>
<Name>XYZ</Name>
<Ref>54321</Ref>
<Status>O</Status>
<Details>
<Detail>
<Currency>AUD</Currency>
<Date>2016-03-01</Date>
</Detail>
<Detail>
<Currency>USD</Currency>
<Date>2016-05-01</Date>
</Detail>
</Details>
</row>
</Output>
Any help ?
Tried using the below xslt , but the if condition isn't working
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:output method="xml" version="1.0"/>
<xsl:template match="/">
<xsl:element name="Output">
<xsl:apply-templates select="Input"/>
</xsl:element>
</xsl:template>
<xsl:template match="Input">
<xsl:for-each select="row">
<xsl:if test="(following-sibling::Ref = /Ref)">
<xsl:element name="row">
<xsl:element name="Name">
<xsl:value-of select="Name" />
</xsl:element>
<xsl:element name="Ref">
<xsl:value-of select="Ref" />
</xsl:element>
<xsl:element name="Status">
<xsl:value-of select="Status" />
</xsl:element>
<xsl:element name="Details">
<xsl:element name="Detail">
<xsl:element name="Currency">
<xsl:value-of select="Currency" />
</xsl:element>
<xsl:element name="Date">
<xsl:value-of select="Date" />
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kRowByRefNameStat" match="row" use="concat(Name, '|', Ref, '|', Status)"/>
<xsl:template match="/*">
<Output>
<xsl:apply-templates select=
"row[generate-id()
=
generate-id(key('kRowByRefNameStat',
concat(Name, '|', Ref, '|', Status))[1])]"/>
</Output>
</xsl:template>
<xsl:template match="row">
<row>
<xsl:copy-of select="Name | Ref | Status"/>
<Details>
<xsl:apply-templates mode="inGroup" select=
"key('kRowByRefNameStat', concat(Name, '|', Ref, '|', Status))"/>
</Details>
</row>
</xsl:template>
<xsl:template match="row" mode="inGroup">
<Detail><xsl:copy-of select="Currency | Date"/></Detail>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<Input>
<row>
<Name>ABC</Name>
<Ref>12345</Ref>
<Status>O</Status>
<Currency>USD</Currency>
<Date>2016-05-16</Date>
</row>
<row>
<Name>ABC</Name>
<Ref>12345</Ref>
<Status>O</Status>
<Currency>AUD</Currency>
<Date>2016-05-01</Date>
</row>
<row>
<Name>XYZ</Name>
<Ref>54321</Ref>
<Status>O</Status>
<Currency>AUD</Currency>
<Date>2016-03-01</Date>
</row>
<row>
<Name>XYZ</Name>
<Ref>54321</Ref>
<Status>O</Status>
<Currency>USD</Currency>
<Date>2016-05-01</Date>
</row>
</Input>
produces the wanted, correct result:
<Output>
<row>
<Name>ABC</Name>
<Ref>12345</Ref>
<Status>O</Status>
<Details>
<Detail>
<Currency>USD</Currency>
<Date>2016-05-16</Date>
</Detail>
<Detail>
<Currency>AUD</Currency>
<Date>2016-05-01</Date>
</Detail>
</Details>
</row>
<row>
<Name>XYZ</Name>
<Ref>54321</Ref>
<Status>O</Status>
<Details>
<Detail>
<Currency>AUD</Currency>
<Date>2016-03-01</Date>
</Detail>
<Detail>
<Currency>USD</Currency>
<Date>2016-05-01</Date>
</Detail>
</Details>
</row>
</Output>
Explanation:
Muenchian grouping using composite-keys
Modes

H2 refine XSLT to transform Shopify XML for FileMaker import

I'm trying to transform the following Shopify XML ...
<orders>
<order>
<order-no>1001</order-no>
<line-items>
<line-item>
<product-id>knife</product-id>
</line-item>
<line-item>
<product-id>fork</product-id>
</line-item>
</line-items>
<shipping-address>
<post-code>rh10 3hs</post-code>
</shipping-address>
</order>
</orders>
to the FileMaker FMPXMLRESULT grammer..
<ROW>
<COL>
<DATA>1001</DATA>
</COL>
<COL>
<DATA>Knife</DATA>
</COL>
<COL>
<DATA>rh10 3hs</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>1001</DATA>
</COL>
<COL>
<DATA>Fork</DATA>
</COL>
<COL>
<DATA>rh10 3hs</DATA>
</COL>
</ROW>
i.e.
1001 Knife rh10 3hs
1001 Fork rh10 3hs
using a FileMaker xslt example...
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/*">
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<ERRORCODE>0</ERRORCODE>
<PRODUCT BUILD="" NAME="" VERSION=""/>
<DATABASE DATEFORMAT="M/d/yyyy" LAYOUT="" NAME="" RECORDS="{count(/*/*)}" TIMEFORMAT="h:mm:ss a"/>
<METADATA>
<xsl:for-each select="/*/*[position()=1]/*">
<FIELD>
<xsl:attribute name="EMPTYOK">YES</xsl:attribute>
<xsl:attribute name="MAXREPEAT">1</xsl:attribute>
<xsl:attribute name="NAME"><xsl:value-of select="name()"/></xsl:attribute>
<xsl:attribute name="TYPE">TEXT</xsl:attribute>
</FIELD>
</xsl:for-each>
</METADATA>
<RESULTSET>
<xsl:attribute name="FOUND"><xsl:value-of select="count(child::*)"/></xsl:attribute>
<xsl:for-each select="child::*">
<ROW>
<xsl:attribute name="MODID">0</xsl:attribute>
<xsl:attribute name="RECORDID">0</xsl:attribute>
<xsl:for-each select="child::*">
<COL>
<DATA>
<xsl:value-of select="."/>
</DATA>
</COL>
</xsl:for-each>
</ROW>
</xsl:for-each>
</RESULTSET>
</FMPXMLRESULT>
</xsl:template>
</xsl:stylesheet>
BUT this extracts the top level order details for each order ignoring the children and grandchildren.
I'm a complete beginner and have trawled the net and forums trying many permutations of the line '' but to be honest it's guess work and initial elation is begin replaced by desperation ;-(
Any tips greatly appreciated
Many thanks,
Jim
In Filemaker, you can only import into one table at a time. You need a separate stylesheet for each import. This one for importing into the LineItems table:
<?xml version="1.0" encoding="UTF-8"?>
<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:template match="/">
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<ERRORCODE>0</ERRORCODE>
<PRODUCT BUILD="" NAME="" VERSION=""/>
<DATABASE DATEFORMAT="" LAYOUT="" NAME="" RECORDS="" TIMEFORMAT=""/>
<METADATA>
<FIELD NAME="OrderID" TYPE="TEXT" EMPTYOK="YES" MAXREPEAT=""/>
<FIELD NAME="ProductID" TYPE="TEXT" EMPTYOK="YES" MAXREPEAT=""/>
</METADATA>
<RESULTSET FOUND="">
<xsl:for-each select="orders/order/line-items/line-item">
<ROW MODID="" RECORDID="">
<COL><DATA><xsl:value-of select="../../order-no"/></DATA></COL>
<COL><DATA><xsl:value-of select="product-id"/></DATA></COL>
</ROW>
</xsl:for-each>
</RESULTSET>
</FMPXMLRESULT>
</xsl:template>
</xsl:stylesheet>
and this one for importing into the Orders table:
<?xml version="1.0" encoding="UTF-8"?>
<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:template match="/">
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<ERRORCODE>0</ERRORCODE>
<PRODUCT BUILD="" NAME="" VERSION=""/>
<DATABASE DATEFORMAT="" LAYOUT="" NAME="" RECORDS="" TIMEFORMAT=""/>
<METADATA>
<FIELD NAME="OrderID" TYPE="TEXT" EMPTYOK="YES" MAXREPEAT=""/>
<FIELD NAME="PostCode" TYPE="TEXT" EMPTYOK="YES" MAXREPEAT=""/>
</METADATA>
<RESULTSET FOUND="">
<xsl:for-each select="orders/order">
<ROW MODID="" RECORDID="">
<COL><DATA><xsl:value-of select="order-no"/></DATA></COL>
<COL><DATA><xsl:value-of select="shipping-address/post-code"/></DATA></COL>
</ROW>
</xsl:for-each>
</RESULTSET>
</FMPXMLRESULT>
</xsl:template>
</xsl:stylesheet>