I have a problem in order to convert a file that looks like this into a "flat" table These files are uploaded during the exchange. There are many of them, but they have one template. First a description of the headers, then only the values.
<?xml version="1.0" encoding="UTF-8"?>
<extdata user="test">
<scheme name="CRMOrder" request="get" success="true">
<data>
<s>
<d name="CRMOrder">
<f name="ActionDate" type="Date" />
<f name="CRMClientId" type="String" />
<f name="CreateId" type="Date" />
<f name="StatusId" type="String" />
<f name="Summa" type="Decimal" />
<f name="WareHouseId" type="String" />
<d name="CRMOrderLine">
<f name="Price" type="Decimal" />
<f name="LineNumber" type="Integer" />
<f name="Quantity" type="Decimal" />
<f name="Discount" type="Integer" />
</d>
<d name="CRMOrderOption">
<f name="OptionTypeId" type="String" />
<f name="Value" type="String" />
<f name="OptionTypeName" type="String" />
</d>
</d>
</s>
<o>
<d name="CRMOrder">
<r>
<f>2022-01-11T00:00:00</f>
<f>69244</f>
<f>2142256774</f>
<f>Accepted</f>
<f>2318.0600</f>
<f>62</f>
<d name="CRMOrderLine">
<r>
<f>64.7800</f>
<f>1</f>
<f>18.0000</f>
<f>62</f>
</r>
<d name="CRMOrderOption">
<r>
<f>2022-01-10T00:00:00</f>
<f>Comment</f>
<f>1</f>
</r>
</d>
</d>
</r>
</d>
</o>
</data>
</scheme>
</extdata>
XSLT
<?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/data">
<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">
<-- get the total number of columns -->
<xsl:variable name="recordColumn" select="count(s/d/f/@name) + count(s/d/d/f/@name)" />
<-- I didn’t understand how to create headers in one cycle, so there are two cycles with the same content -->
<xsl:for-each select="s/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="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="o/d/r/f">
<-- Problem is here -->
<xsl:variable name="counter" select="position()" />
<xsl:if test="$counter = 1">
<xsl:text disable-output-escaping="yes"><row></xsl:text>
</xsl:if>
<xsl:if test="$counter mod $recordColumn = 0">
<xsl:text disable-output-escaping="yes"></row></xsl:text>
<xsl:if test="$counter != last() ">
<xsl:text disable-output-escaping="yes"><row></xsl:text>
</xsl:if>
</xsl:if>
<xsl:if test="$counter mod $recordColumn != 0">
<Value>
<xsl:value-of select="." />
</Value>
</xsl:if>
</xsl:for-each>
</ValueTable>
</xsl:template>
</xsl:stylesheet>
How do i get the table from this file. The beginning and end of the row about the string and value probably did not look very beautiful, but it works. There are now 12 columns, as a result, my table row contains only 6 first values.
Expected result
<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">CRMClientId</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">CreateId</Name>
<ValueType>
<Type>xs:dateTime</Type>
<DateQualifiers>
<DateFractions>DateTime</DateFractions>
</DateQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">StatusId</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">Summa</Name>
<ValueType>
<Type>xs:decimal</Type>
<NumberQualifiers>
<Digits>20</Digits>
<FractionDigits>4</FractionDigits>
<AllowedSign>Any</AllowedSign>
</NumberQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">WareHouseId</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">Price</Name>
<ValueType>
<Type>xs:decimal</Type>
<NumberQualifiers>
<Digits>20</Digits>
<FractionDigits>4</FractionDigits>
<AllowedSign>Any</AllowedSign>
</NumberQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">LineNumber</Name>
<ValueType>
<Type>xs:decimal</Type>
<NumberQualifiers>
<Digits>20</Digits>
<FractionDigits>0</FractionDigits>
<AllowedSign>Any</AllowedSign>
</NumberQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">Quantity</Name>
<ValueType>
<Type>xs:decimal</Type>
<NumberQualifiers>
<Digits>20</Digits>
<FractionDigits>4</FractionDigits>
<AllowedSign>Any</AllowedSign>
</NumberQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">Discount</Name>
<ValueType>
<Type>xs:decimal</Type>
<NumberQualifiers>
<Digits>20</Digits>
<FractionDigits>0</FractionDigits>
<AllowedSign>Any</AllowedSign>
</NumberQualifiers>
</ValueType>
</column>
<Name xsi:type="xs:string">OptionTypeId</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">Value</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<column>
<Name xsi:type="xs:string">OptionTypeName</Name>
<ValueType>
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</ValueType>
</column>
<row>
<Value>2022-01-11T00:00:00</Value>
<Value>69244</Value>
<Value>2142256774</Value>
<Value>Accepted</Value>
<Value>2318.0600</Value>
<Value>62</Value>
<Value>64.7800</Value>
<Value>1</Value>
<Value>18.0000</Value>
<Value>62</Value>
<Value>2022-01-10T00:00:00</Value>
<Value>Comment</Value>
<Value>1</Value>
</row>
</ValueTable>
The given example is somewhat ambiguous. Assuming that s
is the header row, and that o
is a data row containing exactly one value for each column in the header row, and in the same order (IOW, that the input is already a "flat" table), the result shown could be produced using:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/extdata">
<ValueTable>
<!-- header -->
<xsl:for-each select="scheme/data/s//f">
<column>
<Name xsi:type="xs:string">
<xsl:value-of select="@name"/>
</Name>
<ValueType>
<xsl:choose>
<xsl:when test="@type= 'String'">
<Type>xs:string</Type>
<StringQualifiers>
<Length>150</Length>
<AllowedLength>Variable</AllowedLength>
</StringQualifiers>
</xsl:when>
<xsl:when test="@type='Date'">
<Type>xs:dateTime</Type>
<DateQualifiers>
<DateFractions>DateTime</DateFractions>
</DateQualifiers>
</xsl:when>
<xsl:when test="@type='Decimal' or @type='Currency'">
<Type>xs:decimal</Type>
<NumberQualifiers>
<Digits>20</Digits>
<FractionDigits>4</FractionDigits>
<AllowedSign>Any</AllowedSign>
</NumberQualifiers>
</xsl:when>
<xsl:when test="@type='Integer'">
<Type>xs:decimal</Type>
<NumberQualifiers>
<Digits>20</Digits>
<FractionDigits>0</FractionDigits>
<AllowedSign>Any</AllowedSign>
</NumberQualifiers>
</xsl:when>
</xsl:choose>
</ValueType>
</column>
</xsl:for-each>
<!-- data -->
<xsl:for-each select="scheme/data/o">
<row>
<xsl:for-each select=".//f">
<Value>
<xsl:value-of select="."/>
</Value>
</xsl:for-each>
</row>
</xsl:for-each>
</ValueTable>
</xsl:template>
</xsl:stylesheet>