#xslt #conditional
#xslt #условные операторы
Вопрос:
Возможно ли выполнить условное суммирование в xsl?
У меня есть следующий образец xml:
<?xml version="1.0" encoding="utf-8"?>
<export>
<stats set="1">
<columns>
<column id="0">
<sum>100</sum>
</column>
<column id="1">
<sum>102</sum>
</column>
<column id="2">
<sum>12</sum>
</column>
</columns>
</stats>
<stats set="2">
<columns>
<column id="0">
<sum>100</sum>
</column>
<column id="1">
<sum>101</sum>
</column>
<column id="2">
<sum>19</sum>
</column>
</columns>
</stats>
</export>
Возможно ли вычислить общее количество всех столбцов в каждом наборе статистики, где они не равны друг другу? Таким образом, это привело бы к следующему:
Set 1 Set 2 Diff(Set 1 - Set 2)
Total (Diff) 114 120 -6
column 2 102 101 1
column 3 12 19 -7
Таким образом, в выходном столбце 1 будет опущен, поскольку сумма в двух наборах статистики одинакова.
Я могу заставить свой xsl выводить столбцы, которые отличаются, но не уверен, как их суммировать и поместить в итоговую строку.
Большое спасибо,
Иез
Комментарии:
1. Отредактируйте свой пост, чтобы включить свой XSL
2. Отличный вопрос, 1. Смотрите мой ответ для получения полного и эффективного решения и подробных объяснений. 🙂
Ответ №1:
Это преобразование (64 строки):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kColByPosAndVal" match="column"
use="concat(count(preceding-sibling::*),
' ',
sum)"/>
<xsl:key name="kIdByVal" match="column/@id"
use="."/>
<xsl:template match="/*">
<xsl:variable name="vsum1" select=
"sum(stats[@set=1]/*/column
[not(key('kColByPosAndVal',
concat(count(preceding-sibling::*),
' ',
sum)
)[2]
)])"/>
<xsl:variable name="vsum2" select=
"sum(stats[@set=2]/*/column
[not(key('kColByPosAndVal',
concat(count(preceding-sibling::*),
' ',
sum)
)[2]
)])"/>
Set 1 Set 2 Diff(Set 1 - Set 2)
Total (Diff) <xsl:text/>
<xsl:value-of select="$vsum1"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vsum2"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vsum1 -$vsum2"/>
<xsl:text>amp;#xA;</xsl:text>
<xsl:for-each select=
"*/*/column/@id
[generate-id()
= generate-id(key('kIdByVal',.)[1])
]
[not(key('kColByPosAndVal',
concat(count(../preceding-sibling::*),
' ',
../sum)
)[2]
)]">
<xsl:variable name="vcolSet1" select=
"/*/stats[@set=1]/*/column[@id=current()]/sum"/>
<xsl:variable name="vcolSet2" select=
"/*/stats[@set=2]/*/column[@id=current()]/sum"/>
Column <xsl:value-of select=". 1"/><xsl:text/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vcolSet1"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vcolSet2"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$vcolSet1 -$vcolSet2"/>
<xsl:text>amp;#xA;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному XML-документу:
<export>
<stats set="1">
<columns>
<column id="0">
<sum>100</sum>
</column>
<column id="1">
<sum>102</sum>
</column>
<column id="2">
<sum>12</sum>
</column>
</columns>
</stats>
<stats set="2">
<columns>
<column id="0">
<sum>100</sum>
</column>
<column id="1">
<sum>101</sum>
</column>
<column id="2">
<sum>19</sum>
</column>
</columns>
</stats>
</export>
выдает желаемый, правильный результат:
Set 1 Set 2 Diff(Set 1 - Set 2)
Total (Diff) 114 120 -6
Column 2 102 101 1
Column 3 12 19 -7
Объяснение:
-
Ключ с именем
kColByPosAndVal
используется для выбора всех столбцов, которые имеют заданную позицию (среди всехcolumn
братьев и сестер) и заданное значение для ихsum
дочернего элемента. -
Указанный ключ
kIdByVal
используется в группировке по-мюнхенски для поиска всех различных значений дляid
атрибута. -
Два итога вычисляются с суммированием только тех столбцов,
kColByPosAndVal
ключ которых выбирает только одинcolumn
элемент (если он выбирает дваcolumn
элемента, они оба находятся в одной позиции и имеют одинаковый размерsum
). -
Остальное должно быть легко понять.
Комментарии:
1. Спасибо за это, Дмитрий. Я попробую это в ближайшее время.
2. извините, рабочая нагрузка просто зашкалила, поэтому мне пришлось отложить это на второй план. Я только сейчас начинаю смотреть на это
3. отлично, спасибо. Я попробовал, и это делает то, на что я надеялся. Кроме того, спасибо за пояснения — они действительно помогают — я все еще относительно новичок в XSL. Приветствую, Андез