xsl группировка повторяющихся узлов по элементу xml в xslt1
У меня есть сложная структура XML, которая выглядит следующим образом:
<Items>
<Item>
<ItemTexts>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
<ItemTextsLine>1</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
<ItemTextsLine>2</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
<ItemTextsLine>3</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
<ItemTextsLine>4</ItemTextsLine>
</ItemText>
</ItemTexts>
</Item>
<Item>
<ItemTexts>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
<ItemTextsLine>1</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
<ItemTextsLine>2</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
<ItemTextsLine>3</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
<ItemTextsLine>4</ItemTextsLine>
</ItemText>
</ItemTexts>
</Item>
<Item>
<ItemTexts>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
<ItemTextsLine>1</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
<ItemTextsLine>2</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
<ItemTextsLine>3</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
<ItemTextsLine>4</ItemTextsLine>
</ItemText>
</ItemTexts>
</Item>
<Item>
<ItemTexts>
<ItemText>
<ItemTextsType>type3</ItemTextsType>
<ItemTextsTypeDesc>description31</ItemTextsTypeDesc>
<ItemTextsLine>1</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type3</ItemTextsType>
<ItemTextsTypeDesc>description32</ItemTextsTypeDesc>
<ItemTextsLine>2</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
<ItemTextsLine>3</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
<ItemTextsLine>4</ItemTextsLine>
</ItemText>
</ItemTexts>
</Item>
</Items>
Я использую xsl для каждого элемента, например:
<xsl:for-each select="Items/Item">
Мне нужен пример того, как группировать <ItemText>
от <ItemTextsType>
индивидуально для каждого <Item>
итак результат будет такой:
Для первого <Item>
в этом примере:
Тип 1
description11 description12
типа2
description21
description22
Для второго Item
в этом примере:
3тип
description31 description32
типа2
description21
description22
конечно я организую результат в таблице как:
<table width="100%" border="1" style="display: block;">
<tbody>
<tr>
<td id="SelectedRowLinkageContents">
<table width="100%" dir="ltr">
<tbody>
<tr style="background-color: #507CD1; text-align: center">
<td colspan="3" style="font: bold; color: white">
Item1
</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">
type1
</td>
</tr>
<tr>
<td>
desription11
</td>
</tr>
<tr>
<td>
desription12
</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">
type2
</td>
</tr>
<tr>
<td>
desription21
</td>
</tr>
<tr>
<td>
desription22
</td>
</tr>
<tr>
<td>
desription23
</td>
</tr>
</tbody>
</table>
<table width="100%" dir="ltr">
<tbody>
<tr style="background-color: #507CD1; text-align: center">
<td colspan="3" style="font: bold; color: white">
Item2
</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">
type1
</td>
</tr>
<tr>
<td>
desription11
</td>
</tr>
<tr>
<td>
desription12
</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">
type2
</td>
</tr>
<tr>
<td>
desription21
</td>
</tr>
<tr>
<td>
desription23
</td>
</tr>
</tbody>
</table>
<table width="100%" dir="ltr">
<tbody>
<tr style="background-color: #507CD1; text-align: center">
<td colspan="3" style="font: bold; color: white">
Item3
</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">
type1
</td>
</tr>
<tr>
<td>
desription11
</td>
</tr>
<tr>
<td>
desription12
</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">
type2
</td>
</tr>
<tr>
<td>
desription21
</td>
</tr>
<tr>
<td>
desription23
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
Дело в том, что существует отдельная группировка для каждого <Item>
в свое собственное <table>
и внутри этого <table>
там глотает <ItemTextsType>
Я пробовал что-то вроде
<xsl:key name="item-texts-type" match="ItemText" use="ItemTextsType" />
<xsl:for-each select="ItemTexts/ItemText[count(. | key('item-texts-type', ItemTextsType)[1]) = 1]">
<xsl:sort select="ItemTextsType" />
<tr>
<td style ="height:35px;font: bold; color:#507CD1;">
<xsl:value-of select="ItemTextsType" />
</td>
</tr>
<xsl:for-each select="key('item-texts-type', ItemTextsType)">
<tr>
<td>
<xsl:value-of select="ItemTextsTypeDesc" />
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
но он работает только на неповторяющихся узлах (если был только один <Item>
это будет работать нормально). Я не могу изменить XML, потому что это исходит от клиента.
Пожалуйста, помогите мне, мне это нужно как можно скорее.
Спасибо!!!!
1 ответ
Из-за некоторых расхождений все еще трудно сказать, какое искомое решение имеет место - например, ваш входной XML имеет 4 <Item>
элементы, но желаемый результат учитывает только 3 из них. Кроме того, несколько описаний в желаемом выводе не совпадают с их ожидаемым расположением во входном XML-документе.
Тем не менее, если мы сосредоточимся на вашем заявленном желаемом решении:
"Дело в том, что существует отдельная группировка для каждого
<Item>
в свое собственное<table>
и внутри этого<table>
там глотает<ItemTextsType>
"
... тогда это должно привести вас в правильном направлении.
Когда это XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:key
name="kItemTextByType"
match="ItemText"
use="concat(generate-id(ancestor::Item[1]), '+', ItemTextsType)" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<table width="100%" border="1" style="display: block;">
<tbody>
<tr>
<td id="SelectedRowLinkageContents">
<xsl:apply-templates />
</td>
</tr>
</tbody>
</table>
</xsl:template>
<xsl:template match="Item">
<table width="100%" dir="ltr">
<tbody>
<tr style="background-color: #507CD1; text-align: center">
<td colspan="3" style="font: bold; color: white">
<xsl:value-of select="concat('Item', position())" />
</td>
</tr>
<xsl:apply-templates
select="ItemTexts/ItemText[
generate-id() =
generate-id(
key(
'kItemTextByType',
concat(generate-id(current()), '+', ItemTextsType)
)[1]
)
]">
<xsl:sort select="ItemTextsType" />
</xsl:apply-templates>
</tbody>
</table>
</xsl:template>
<xsl:template match="ItemText">
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">
<xsl:value-of select="ItemTextsType" />
</td>
</tr>
<xsl:for-each
select="key(
'kItemTextByType',
concat(
generate-id(ancestor::Item[1]),
'+',
ItemTextsType
)
)"
>
<xsl:sort select="ItemTextsTypeDesc" />
<tr>
<td>
<xsl:value-of select="ItemTextsTypeDesc" />
</td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
... применяется к предоставленному входному XML:
<?xml version="1.0" encoding="UTF-8"?>
<Items>
<Item>
<ItemTexts>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
<ItemTextsLine>1</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
<ItemTextsLine>2</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
<ItemTextsLine>3</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
<ItemTextsLine>4</ItemTextsLine>
</ItemText>
</ItemTexts>
</Item>
<Item>
<ItemTexts>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
<ItemTextsLine>1</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
<ItemTextsLine>2</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
<ItemTextsLine>3</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
<ItemTextsLine>4</ItemTextsLine>
</ItemText>
</ItemTexts>
</Item>
<Item>
<ItemTexts>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description11</ItemTextsTypeDesc>
<ItemTextsLine>1</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type1</ItemTextsType>
<ItemTextsTypeDesc>description12</ItemTextsTypeDesc>
<ItemTextsLine>2</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
<ItemTextsLine>3</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
<ItemTextsLine>4</ItemTextsLine>
</ItemText>
</ItemTexts>
</Item>
<Item>
<ItemTexts>
<ItemText>
<ItemTextsType>type3</ItemTextsType>
<ItemTextsTypeDesc>description31</ItemTextsTypeDesc>
<ItemTextsLine>1</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type3</ItemTextsType>
<ItemTextsTypeDesc>description32</ItemTextsTypeDesc>
<ItemTextsLine>2</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description21</ItemTextsTypeDesc>
<ItemTextsLine>3</ItemTextsLine>
</ItemText>
<ItemText>
<ItemTextsType>type2</ItemTextsType>
<ItemTextsTypeDesc>description22</ItemTextsTypeDesc>
<ItemTextsLine>4</ItemTextsLine>
</ItemText>
</ItemTexts>
</Item>
</Items>
... желаемый результат получается (я думаю):
<table width="100%" border="1" style="display: block;">
<tbody>
<tr>
<td id="SelectedRowLinkageContents">
<table width="100%" dir="ltr">
<tbody>
<tr style="background-color: #507CD1; text-align: center">
<td colspan="3" style="font: bold; color: white">Item1</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">type1</td>
</tr>
<tr>
<td>description11</td>
</tr>
<tr>
<td>description12</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">type2</td>
</tr>
<tr>
<td>description21</td>
</tr>
<tr>
<td>description22</td>
</tr>
</tbody>
</table>
<table width="100%" dir="ltr">
<tbody>
<tr style="background-color: #507CD1; text-align: center">
<td colspan="3" style="font: bold; color: white">Item2</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">type1</td>
</tr>
<tr>
<td>description11</td>
</tr>
<tr>
<td>description12</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">type2</td>
</tr>
<tr>
<td>description21</td>
</tr>
<tr>
<td>description22</td>
</tr>
</tbody>
</table>
<table width="100%" dir="ltr">
<tbody>
<tr style="background-color: #507CD1; text-align: center">
<td colspan="3" style="font: bold; color: white">Item3</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">type1</td>
</tr>
<tr>
<td>description11</td>
</tr>
<tr>
<td>description12</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">type2</td>
</tr>
<tr>
<td>description21</td>
</tr>
<tr>
<td>description22</td>
</tr>
</tbody>
</table>
<table width="100%" dir="ltr">
<tbody>
<tr style="background-color: #507CD1; text-align: center">
<td colspan="3" style="font: bold; color: white">Item4</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">type2</td>
</tr>
<tr>
<td>description21</td>
</tr>
<tr>
<td>description22</td>
</tr>
<tr>
<td style="height: 35px; font: bold; color: #507CD1;">
type3</td>
</tr>
<tr>
<td>description31</td>
</tr>
<tr>
<td>description32</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
... который при рендеринге на HTML-странице выглядит следующим образом: