Группировка братьев и сестер, заканчивающаяся соответствующим элементом
У меня очень большой XSL-файл для преобразования XML в CSV. По сути, структура XML - это табличные данные. В этой таблице около 90 столбцов (не мое решение!). Эти столбцы составляют группу столбцов.
У каждой группы столбцов есть Первое и Второе значение, необязательное Третье значение и Выбор, который решает, какое значение было выбрано в группе - это обозначено как F, S или T - (F)irst/(S)econd/(T) Hird. Основным ключом в строке является столбец Дата и время.
XML выглядит следующим образом (это не урезанная версия). Так что мы могли бы сказать, например, столбец 30.
<data>
<columns>
<column id="0">
<name>Date Time</name>
<type>DateTime</type>
</column>
<column id="1">
<name>Column Group 1 First</name>
<type>Double</type>
</column>
<column id="2">
<name>Column Group 1 Second</name>
<type>Double</type>
</column>
<column id="3">
<name>Column Group 1 Third</name>
<type>Double</type>
</column>
<column id="4">
<name>Column Group 1 Selection</name>
<type>String</type>
</column>
<column id="5">
<name>Column Group 2 First</name>
<type>Double</type>
</column>
<column id="6">
<name>Column Group 2 Second</name>
<type>Double</type>
</column>
<column id="7">
<name>Column Group 2 Third</name>
<type>Double</type>
</column>
<column id="8">
<name>Column Group 2 Selection</name>
<type>String</type>
</column>
<!-- This group does not have Third-->
<column id="9">
<name>Column Group 3 First</name>
<type>Double</type>
</column>
<column id="10">
<name>Column Group 3 Second</name>
<type>Double</type>
</column>
<column id="11">
<name>Column Group 3 Selection</name>
<type>String</type>
</column>
</columns>
<rows>
<row id="0">
<columns>
<column id="0">
<name>Date Time</name>
<universalDate>2010-10-10 11:30:00</universalDate>
</column>
<!-- Group 1 - - - - - - - - - - - - - - - - -->
<column id="1">
<name>Column Group 1 First</name>
<displayValue>100.123</displayValue>
<value>100.123</value>
</column>
<column id="2">
<name>Column Group 1 Second</name>
<displayValue>Missing</displayValue>
<value>-2.50E+08</value>
</column>
<column id="3">
<name>Column Group 1 Third</name>
<displayValue>Missing</displayValue>
<value>-2.50E+08</value>
</column>
<column id="4">
<name>Column Group 1 Selection</name>
<displayValue>F</displayValue>
<value>F</value>
</column>
<!-- Group 2 - - - - - - - - - - - - - - - - -->
<column id="5">
<name>Column Group 2 First</name>
<displayValue>Missing</displayValue>
<value>-2.50E+08</value>
</column>
<column id="6">
<name>Column Group 2 Second</name>
<displayValue>Missing</displayValue>
<value>-2.50E+08</value>
</column>
<column id="7">
<name>Column Group 2 Third</name>
<displayValue>93.123</displayValue>
<value>93.123</value>
</column>
<column id="8">
<name>Column Group 2 Selection</name>
<displayValue>T</displayValue>
<value>T</value>
</column>
<!-- Group 3 - - - - - - - - - - - - - - - - -->
<column id="9">
<name>Column Group 3 First</name>
<displayValue>500.3</displayValue>
<value>500.3</value>
</column>
<column id="10">
<name>Column Group 3 Second</name>
<displayValue>22.21</displayValue>
<value>22.21</value>
</column>
<column id="11">
<name>Column Group 3 Third</name>
<displayValue>S</displayValue>
<value>S</value>
</column>
</columns>
</row>
<!-- Other rows omitted -->
</rows>
</data>
Желаемый результат будет:
Date Time,Column Group 1 Primary,Column Group 1 Secondary,Column Group 1 Third,Column Group 1 Selection
Date Time,Column Group 2 Primary,Column Group 2 Secondary,Column Group 2 Third,Column Group 2 Selection
Date Time,Column Group 3 Primary,Column Group 3 Secondary,Column Group 3 Third,Column Group 3 Selection
... and so on ...
Таким образом, результат будет на самом деле:
2010-10-10 11:30:00,100.123,,,F
2010-10-10 11:30:00,,,93.123,T
2010-10-10 11:30:00,500.3,22.21,,S
Есть пара правил: если displayValue = отсутствует, выведите пустую строку. если группа не имеет третьего значения, выведите пустую строку.
Первый экземпляр моего XSL - повторение этой проверки для каждого набора столбцов, который выглядит ужасно и слишком велик.
Вопрос в том - можно ли вывести следующий XML с использованием шаблонов? Я только начал работать над шаблонами (благодаря помощи других в моих других публикациях), но это немного застряло.
Я могу связать столбцы и строки, чтобы вывести все данные столбца строки в таблице xml, но это более или менее группирует 3 столбца вместе на основе первой части имени.
Мой XSL для этого экземпляра выглядит так:
<xsl:for-each select="//rows/row">
<xsl:value-of select="columns/column[name='Date Time']/universalDate"/>
<xsl:text>,</xsl:text>
<xsl:if test="number(columns/column[name='Column 1 First']/value)">
<xsl:value-of select="format-number(columns/column[name='Column 1 First']/value,'0')"/>
</xsl:if>
<xsl:text>,</xsl:text>
<xsl:if test="number(columns/column[name='Column 1 Second']/value)">
<xsl:value-of select="format-number(columns/column[name='Column 1 Second']/value,'0')"/>
</xsl:if>
<xsl:text>,</xsl:text>
<xsl:if test="number(columns/column[name='Column 1 Third']/value)">
<xsl:value-of select="format-number(columns/column[name='Column 1 Third']/rawValue,'0')"/>
</xsl:if>
<xsl:text>,</xsl:text>
<xsl:if test="columns/column[name='Column 1 Selection']/value='F'">
<xsl:value-of select="format-number(columns/column[name='Column 1 First']/value,'0')"/>
</xsl:if>
<xsl:if test="columns/column[name='Column 1 Selection']/value='S'">
<xsl:value-of select="format-number(columns/column[name='Column 1 Second']/value,'0')"/>
</xsl:if>
<xsl:if test="columns/column[name='Column 1 Selection']/value='T'">
<xsl:value-of select="format-number(columns/column[name='Column 1 Third']/value,'0')"/>
</xsl:if>
<!-- new line required -->
<xsl:text>
</xsl:text>
<xsl:value-of select="columns/column[name='Date Time']/universalDate"/>
<xsl:text>,</xsl:text>
<xsl:if test="number(columns/column[name='Column 2 First']/value)">
<xsl:value-of select="format-number(columns/column[name='Column 1 First']/value,'0')"/>
</xsl:if>
<xsl:text>,</xsl:text>
<xsl:if test="number(columns/column[name='Column 2 Second']/value)">
<xsl:value-of select="format-number(columns/column[name='Column 1 Second']/value,'0')"/>
</xsl:if>
<xsl:text>,</xsl:text>
<xsl:if test="number(columns/column[name='Column 2 Third']/value)">
<xsl:value-of select="format-number(columns/column[name='Column 2 Third']/value,'0')"/>
</xsl:if>
<xsl:text>,</xsl:text>
<xsl:if test="columns/column[name='Column 2 Selection']/value='F'">
<xsl:value-of select="format-number(columns/column[name='Column 2 First']/value,'0')"/>
</xsl:if>
<xsl:if test="columns/column[name='Column 2 Selection']/value='S'">
<xsl:value-of select="format-number(columns/column[name='Column 2 Second']/value,'0')"/>
</xsl:if>
<xsl:if test="columns/column[name='Column 2 Selection']/value='T'">
<xsl:value-of select="format-number(columns/column[name='Column 2 Third']/value,'0')"/>
</xsl:if>
<!-- new line required -->
<xsl:text>
</xsl:text>
<!-- and so on....... -->
Извините за разъяснения в первых случаях.
Спасибо,
Andez
1 ответ
Эта таблица стилей:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="row/columns/column[substring(name,16)='First']">
<xsl:variable name="vOptional"
select="following::column[2]
[substring(name,16)='Third']"/>
<xsl:value-of select="concat(../column[1]/universalDate,',',
displayValue[.!='Missing'],',',
following::column[1]
/displayValue[.!='Missing'],',',
$vOptional/displayValue[.!='Missing'],',',
following::column[2 + boolean($vOptional)]
/displayValue[.!='Missing'],'
')"/>
</xsl:template>
<xsl:template match="data/columns|column"/>
</xsl:stylesheet>
Выход:
2010-10-10 11:30:00,100.123,,,F
2010-10-10 11:30:00,,,93.123,T
2010-10-10 11:30:00,500.3,22.21,,S
Изменить: лучше. Я был заперт в предыдущей логике, извините.