completely new to xlst, I've tried to follow numerous links to apply Muenchian grouping but to no avail, most likely because I'm not putting the extra lines in the right places probably, and have no idea how to convert to xlst2 in order to use for-each-group instead. Anyway the csv file I'm trying to convert is very simple:
123456789,2021-08-05T00:00:00+00:00,GBP,2099-12-31T00:00:00+00:00,23.00
123456789,2021-07-22T00:00:00+00:00,GBP,2099-07-22T00:00:00+00:00,35.00
123456789,2021-07-06T00:00:00+00:00,GBP,2099-07-13T00:00:00+00:00,39.50
987654321,2021-08-05T00:00:00+00:00,EUR,2099-12-31T00:00:00+00:00,25.95
987654321,2021-07-22T00:00:00+00:00,EUR,2099-07-22T00:00:00+00:00,39.95
987654321,2021-07-06T00:00:00+00:00,EUR,2099-07-13T00:00:00+00:00,44.95
Or in XML format:
<DEMarkdown xmlns="http://F.FlatFileSchema1">
<DEMarkdowns xmlns="">
<sku>123456789</sku>
<valid-from>2021-08-05T00:00:00+00:00</valid-from>
<currency>GBP</currency>
<valid-to>2099-12-31T00:00:00+00:00</valid-to>
<value>23.00</value>
</DEMarkdowns>
<DEMarkdowns xmlns="">
<sku>123456789</sku>
<valid-from>2021-07-22T00:00:00+00:00</valid-from>
<currency>GBP</currency>
<valid-to>2099-07-22T00:00:00+00:00</valid-to>
<value>35.00</value>
</DEMarkdowns>
<DEMarkdowns xmlns="">
<sku>123456789</sku>
<valid-from>2021-07-06T00:00:00+00:00</valid-from>
<currency>GBP</currency>
<valid-to>2099-07-13T00:00:00+00:00</valid-to>
<value>39.50</value>
</DEMarkdowns>
<DEMarkdowns xmlns="">
<sku>987654321</sku>
<valid-from>2021-08-05T00:00:00+00:00</valid-from>
<currency>EUR</currency>
<valid-to>2099-12-31T00:00:00+00:00</valid-to>
<value>25.95</value>
</DEMarkdowns>
<DEMarkdowns xmlns="">
<sku>987654321</sku>
<valid-from>2021-07-22T00:00:00+00:00</valid-from>
<currency>EUR</currency>
<valid-to>2099-07-22T00:00:00+00:00</valid-to>
<value>39.95</value>
</DEMarkdowns>
<DEMarkdowns xmlns="">
<sku>987654321</sku>
<valid-from>2021-07-06T00:00:00+00:00</valid-from>
<currency>EUR</currency>
<valid-to>2099-07-13T00:00:00+00:00</valid-to>
<value>44.95</value>
</DEMarkdowns>
</DEMarkdown>
I've used BizTalk to generate my Flat File Source Schema:
<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns="http://F.FlatFileSchema1" xmlns:b="http://schemas.microsoft.com/BizTalk/2003" targetNamespace="http://F.FlatFileSchema1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:annotation>
<xs:appinfo>
<schemaEditorExtension:schemaInfo namespaceAlias="b" extensionClass="Microsoft.BizTalk.FlatFileExtension.FlatFileExtension" standardName="Flat File" xmlns:schemaEditorExtension="http://schemas.microsoft.com/BizTalk/2003/SchemaEditorExtensions" />
<b:schemaInfo standard="Flat File" codepage="65001" default_pad_char=" " pad_char_type="char" count_positions_by_byte="false" parser_optimization="speed" lookahead_depth="3" suppress_empty_nodes="false" generate_empty_nodes="true" allow_early_termination="false" early_terminate_optional_fields="false" allow_message_breakup_of_infix_root="false" compile_parse_tables="false" root_reference="DEMarkdown" />
</xs:appinfo>
</xs:annotation>
<xs:element name="DEMarkdown">
<xs:annotation>
<xs:appinfo>
<b:recordInfo structure="delimited" child_delimiter_type="hex" child_delimiter="0xD 0xA" child_order="postfix" sequence_number="1" preserve_delimiter_for_empty_data="true" suppress_trailing_delimiters="false" />
</xs:appinfo>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:annotation>
<xs:appinfo>
<groupInfo sequence_number="0" xmlns="http://schemas.microsoft.com/BizTalk/2003" />
</xs:appinfo>
</xs:annotation>
<xs:element maxOccurs="unbounded" name="DEMarkdowns">
<xs:annotation>
<xs:appinfo>
<b:recordInfo structure="delimited" child_delimiter_type="char" child_delimiter="," child_order="infix" sequence_number="1" preserve_delimiter_for_empty_data="true" suppress_trailing_delimiters="false" />
</xs:appinfo>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:annotation>
<xs:appinfo>
<groupInfo sequence_number="0" xmlns="http://schemas.microsoft.com/BizTalk/2003" />
</xs:appinfo>
</xs:annotation>
<xs:element name="sku" type="xs:string">
<xs:annotation>
<xs:appinfo>
<b:fieldInfo justification="left" sequence_number="1" />
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="valid-from" type="xs:dateTime">
<xs:annotation>
<xs:appinfo>
<b:fieldInfo justification="left" sequence_number="2" />
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="currency" type="xs:string">
<xs:annotation>
<xs:appinfo>
<b:fieldInfo justification="left" sequence_number="3" />
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="valid-to" type="xs:dateTime">
<xs:annotation>
<xs:appinfo>
<b:fieldInfo justification="left" sequence_number="4" />
</xs:appinfo>
</xs:annotation>
</xs:element>
<xs:element name="value" type="xs:decimal">
<xs:annotation>
<xs:appinfo>
<b:fieldInfo justification="left" sequence_number="5" />
</xs:appinfo>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
The XML destination schema is this:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dt="http://www.fakewebsite.com/xml/ns/enfinity/6.5/core/impex-dt" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.fakewebsite.com/7.1/bc_pricing/impex" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="enfinity">
<xs:complexType>
<xs:sequence>
<xs:element name="product-price-list">
<xs:complexType>
<xs:sequence>
<xs:element name="display-name" type="xs:string" />
<xs:element name="description" type="xs:string" />
<xs:element name="enabled" type="xs:boolean" />
<xs:element name="priority" type="xs:unsignedByte" />
<xs:element name="target-groups">
<xs:complexType>
<xs:sequence>
<xs:element name="customer-segments">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="customer-segment">
<xs:complexType>
<xs:attribute name="id" type="xs:string" use="required" />
<xs:attribute name="repository-id" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element maxOccurs="unbounded" name="product-price-list-entry">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="price-scale-table">
<xs:complexType>
<xs:sequence>
<xs:element name="valid-from" type="xs:dateTime" />
<xs:element name="valid-to" type="xs:dateTime" />
<xs:element name="price-scale-entries">
<xs:complexType>
<xs:sequence>
<xs:element name="fixed-price-entry">
<xs:complexType>
<xs:sequence>
<xs:element name="value" type="xs:decimal" />
</xs:sequence>
<xs:attribute name="quantity" type="xs:unsignedByte" use="required" />
<xs:attribute name="unit" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="type-code" type="xs:unsignedByte" use="required" />
<xs:attribute name="currency" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="sku" type="xs:unsignedInt" use="required" />
<xs:attribute name="import-mode" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:string" use="required" />
<xs:attribute name="priceType" type="xs:string" use="required" />
<xs:attribute name="import-mode" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="major" type="xs:unsignedByte" use="required" />
<xs:attribute name="minor" type="xs:unsignedByte" use="required" />
<xs:attribute name="family" type="xs:string" use="required" />
<xs:attribute name="branch" type="xs:string" use="required" />
<xs:attribute name="build" type="xs:string" use="required" />
</xs:complexType>
</xs:element>
</xs:schema>
The current output of my XML looks like this at the moment:
<?xml version="1.0" encoding="utf-8"?>
<ns0:enfinity major="6" minor="1" family="enfinity" branch="enterprise" build="build" xmlns:ns0="http://www.fakewebsite.com/7.1/bc_pricing/impex" xmlns:s0="http://F.FlatFileSchema1">
<ns0:product-price-list id="DEMarkdown" priceType="ES_SalePrice" import-mode="UPDATE">
<ns0:display-name>DE Markdown</ns0:display-name>
<ns0:description/>
<ns0:enabled>true</ns0:enabled>
<ns0:priority>1</ns0:priority>
<ns0:target-groups>
<ns0:customer-segments>
<ns0:customer-segment id="Everyone" repository-id="WhiteStuff-DE-Anonymous"/>
<ns0:customer-segment id="IG_RegisteredUsers" repository-id="WhiteStuff-DE-Anonymous"/>
</ns0:customer-segments>
</ns0:target-groups>
<ns0:product-price-list-entry sku="123456789" import-mode="REPLACE">
<ns0:price-scale-table type-code="1" currency="GBP">
<ns0:valid-from>2021-08-05T00:00:00+00:00</ns0:valid-from>
<ns0:valid-to>2099-12-31T00:00:00+00:00</ns0:valid-to>
<ns0:price-scale-entries>
<ns0:fixed-price-entry quantity="1" unit="">
<ns0:value>23.00</ns0:value>
</ns0:fixed-price-entry>
</ns0:price-scale-entries>
</ns0:price-scale-table>
</ns0:product-price-list-entry>
<ns0:product-price-list-entry sku="123456789" import-mode="REPLACE">
<ns0:price-scale-table type-code="1" currency="GBP">
<ns0:valid-from>2021-07-22T00:00:00+00:00</ns0:valid-from>
<ns0:valid-to>2099-07-22T00:00:00+00:00</ns0:valid-to>
<ns0:price-scale-entries>
<ns0:fixed-price-entry quantity="1" unit="">
<ns0:value>35.00</ns0:value>
</ns0:fixed-price-entry>
</ns0:price-scale-entries>
</ns0:price-scale-table>
</ns0:product-price-list-entry>
<ns0:product-price-list-entry sku="123456789" import-mode="REPLACE">
<ns0:price-scale-table type-code="1" currency="GBP">
<ns0:valid-from>2021-07-06T00:00:00+00:00</ns0:valid-from>
<ns0:valid-to>2099-07-13T00:00:00+00:00</ns0:valid-to>
<ns0:price-scale-entries>
<ns0:fixed-price-entry quantity="1" unit="">
<ns0:value>39.50</ns0:value>
</ns0:fixed-price-entry>
</ns0:price-scale-entries>
</ns0:price-scale-table>
</ns0:product-price-list-entry>
<ns0:product-price-list-entry sku="987654321" import-mode="REPLACE">
<ns0:price-scale-table type-code="1" currency="EUR">
<ns0:valid-from>2021-08-05T00:00:00+00:00</ns0:valid-from>
<ns0:valid-to>2099-12-31T00:00:00+00:00</ns0:valid-to>
<ns0:price-scale-entries>
<ns0:fixed-price-entry quantity="1" unit="">
<ns0:value>25.95</ns0:value>
</ns0:fixed-price-entry>
</ns0:price-scale-entries>
</ns0:price-scale-table>
</ns0:product-price-list-entry>
<ns0:product-price-list-entry sku="987654321" import-mode="REPLACE">
<ns0:price-scale-table type-code="1" currency="EUR">
<ns0:valid-from>2021-07-22T00:00:00+00:00</ns0:valid-from>
<ns0:valid-to>2099-07-22T00:00:00+00:00</ns0:valid-to>
<ns0:price-scale-entries>
<ns0:fixed-price-entry quantity="1" unit="">
<ns0:value>39.95</ns0:value>
</ns0:fixed-price-entry>
</ns0:price-scale-entries>
</ns0:price-scale-table>
</ns0:product-price-list-entry>
<ns0:product-price-list-entry sku="987654321" import-mode="REPLACE">
<ns0:price-scale-table type-code="1" currency="EUR">
<ns0:valid-from>2021-07-06T00:00:00+00:00</ns0:valid-from>
<ns0:valid-to>2099-07-13T00:00:00+00:00</ns0:valid-to>
<ns0:price-scale-entries>
<ns0:fixed-price-entry quantity="1" unit="">
<ns0:value>44.95</ns0:value>
</ns0:fixed-price-entry>
</ns0:price-scale-entries>
</ns0:price-scale-table>
</ns0:product-price-list-entry>
</ns0:product-price-list>
</ns0:enfinity>
But I want to group by sku so each sku only appears once within product-price-list-entry, so that it looks like this instead:
<enfinity xsi:schemaLocation="http://www.fakewebsite.com/7.1/bc_pricing/impex bc_pricing.xsd" xmlns="http://www.fakewebsite.com/7.1/bc_pricing/impex" xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dt="http://www.fakewebsite.com/6.5/core/impex-dt" major="6" minor="1" family="enfinity" branch="enterprise" build="build">
<product-price-list id="DEMarkdown" priceType="ES_SalePrice" import-mode="UPDATE">
<display-name>DE Markdown</display-name>
<description></description>
<enabled>true</enabled>
<priority>1</priority>
<target-groups>
<customer-segments>
<customer-segment id="Everyone" repository-id="WhiteStuff-DE-Anonymous"/>
<customer-segment id="IG_RegisteredUsers" repository-id="WhiteStuff-DE-Anonymous"/>
</customer-segments>
</target-groups>
<product-price-list-entry sku="123456789" import-mode="REPLACE">
<price-scale-table type-code="1" currency="GBP">
<valid-from>2021-08-05T00:00:00+00:00</valid-from>
<valid-to>2099-12-31T00:00:00+00:00</valid-to>
<price-scale-entries>
<fixed-price-entry quantity="1" unit="">
<value>23.00</value>
</fixed-price-entry>
</price-scale-entries>
</price-scale-table>
<price-scale-table type-code="1" currency="GBP">
<valid-from>2021-07-22T00:00:00+00:00</valid-from>
<valid-to>2099-07-22T00:00:00+00:00</valid-to>
<price-scale-entries>
<fixed-price-entry quantity="1" unit="">
<value>35.00</value>
</fixed-price-entry>
</price-scale-entries>
</price-scale-table>
<price-scale-table type-code="1" currency="EUR">
<valid-from>2021-07-22T00:00:00+00:00</valid-from>
<valid-to>2099-07-22T00:00:00+00:00</valid-to>
<price-scale-entries>
<fixed-price-entry quantity="1" unit="">
<value>39.95</value>
</fixed-price-entry>
</price-scale-entries>
</price-scale-table>
</product-price-list-entry>
<product-price-list-entry sku="987654321" import-mode="REPLACE">
<price-scale-table type-code="1" currency="EUR">
<valid-from>2021-08-05T00:00:00+00:00</valid-from>
<valid-to>2099-12-31T00:00:00+00:00</valid-to>
<price-scale-entries>
<fixed-price-entry quantity="1" unit="">
<value>25.95</value>
</fixed-price-entry>
</price-scale-entries>
</price-scale-table>
<price-scale-table type-code="1" currency="GBP">
<valid-from>2021-07-05T00:00:00+00:00</valid-from>
<valid-to>2099-07-13T00:00:00+00:00</valid-to>
<price-scale-entries>
<fixed-price-entry quantity="1" unit="">
<value>39.50</value>
</fixed-price-entry>
</price-scale-entries>
</price-scale-table>
<price-scale-table type-code="1" currency="EUR">
<valid-from>2021-07-05T00:00:00+00:00</valid-from>
<valid-to>2099-07-13T00:00:00+00:00</valid-to>
<price-scale-entries>
<fixed-price-entry quantity="1" unit="">
<value>44.95</value>
</fixed-price-entry>
</price-scale-entries>
</price-scale-table>
</product-price-list-entry>
</product-price-list>
</enfinity>
The xlst which currently converts csv to xml is this, which is what I'm trying to modify. I've taken out what I tried to add myself as it didn't work :(
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:ns0="http://www.fakewebsite.com/7.1/bc_pricing/impex" xmlns:s0="http://F.FlatFileSchema1">
<xsl:output method="xml" indent="no"/>
<xsl:template match="/">
<xsl:apply-templates select="/s0:DEMarkdown"/>
</xsl:template>
<xsl:template match="/s0:DEMarkdown">
<ns0:enfinity>
<xsl:attribute name="major">
<xsl:text>6</xsl:text>
</xsl:attribute>
<xsl:attribute name="minor">
<xsl:text>1</xsl:text>
</xsl:attribute>
<xsl:attribute name="family">
<xsl:text>enfinity</xsl:text>
</xsl:attribute>
<xsl:attribute name="branch">
<xsl:text>enterprise</xsl:text>
</xsl:attribute>
<xsl:attribute name="build">
<xsl:text>build</xsl:text>
</xsl:attribute>
<ns0:product-price-list>
<xsl:attribute name="id">
<xsl:text>DEMarkdown</xsl:text>
</xsl:attribute>
<xsl:attribute name="priceType">
<xsl:text>ES_SalePrice</xsl:text>
</xsl:attribute>
<xsl:attribute name="import-mode">
<xsl:text>UPDATE</xsl:text>
</xsl:attribute>
<ns0:display-name>
<xsl:text>DE Markdown</xsl:text>
</ns0:display-name>
<ns0:description>
<xsl:text/>
</ns0:description>
<ns0:enabled>
<xsl:text>true</xsl:text>
</ns0:enabled>
<ns0:priority>
<xsl:text>1</xsl:text>
</ns0:priority>
<ns0:target-groups>
<ns0:customer-segments>
<ns0:customer-segment>
<xsl:attribute name="id">
<xsl:text>Everyone</xsl:text>
</xsl:attribute>
<xsl:attribute name="repository-id">
<xsl:text>WhiteStuff-DE-Anonymous</xsl:text>
</xsl:attribute>
</ns0:customer-segment>
<ns0:customer-segment>
<xsl:attribute name="id">
<xsl:text>IG_RegisteredUsers</xsl:text>
</xsl:attribute>
<xsl:attribute name="repository-id">
<xsl:text>WhiteStuff-DE-Anonymous</xsl:text>
</xsl:attribute>
</ns0:customer-segment>
</ns0:customer-segments>
</ns0:target-groups>
<xsl:for-each select="DEMarkdowns">
<ns0:product-price-list-entry>
<xsl:attribute name="sku">
<xsl:value-of select="sku/text()"/>
</xsl:attribute>
<xsl:attribute name="import-mode">
<xsl:text>REPLACE</xsl:text>
</xsl:attribute>
<ns0:price-scale-table>
<xsl:attribute name="type-code">
<xsl:text>1</xsl:text>
</xsl:attribute>
<xsl:attribute name="currency">
<xsl:value-of select="currency/text()"/>
</xsl:attribute>
<ns0:valid-from>
<xsl:value-of select="valid-from/text()"/>
</ns0:valid-from>
<ns0:valid-to>
<xsl:value-of select="valid-to/text()"/>
</ns0:valid-to>
<ns0:price-scale-entries>
<ns0:fixed-price-entry>
<xsl:attribute name="quantity">
<xsl:text>1</xsl:text>
</xsl:attribute>
<xsl:attribute name="unit">
<xsl:text/>
</xsl:attribute>
<ns0:value>
<xsl:value-of select="value/text()"/>
</ns0:value>
</ns0:fixed-price-entry>
</ns0:price-scale-entries>
</ns0:price-scale-table>
</ns0:product-price-list-entry>
</xsl:for-each>
</ns0:product-price-list>
</ns0:enfinity>
</xsl:template>
</xsl:stylesheet>