Всем добрый день!
XSLT только-только начал изучать и вот наткнулся на проблему.
Есть XML-документ следующего вида
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
<?xml version="1.0" encoding="UTF-8"?>
<КаталогТоваров Дата="05.05.2014">
<Раздел Наименование="Косметика и Парфюмерия">
<Номенклатура id="4679"
Наименование="Natural Instinct Освежающий тоник для тела Мандарин 95 мл"
ОписаниеНоменклатуры="Необыкновенный, свежий, искрящийся цитрусовый аромат."
Цена="165" РекомендуемаяРозничнаяЦена="250" РазделКаталогаТоваров="женские"
СписокРазделовКаталогаТоваров="Косметика:Феромоны:женские">
<Описание><![CDATA[Необыкновенный, свежий, искрящийся цитрусовый аромат.]]></Описание>
</Номенклатура>
<Номенклатура id="4680"
Наименование="Natural Instinct Освежающий тоник для тела Малина 95 мл"
ОписаниеНоменклатуры="Нежный, сладкий и благоухающим ароматом, пробуждает инстинкты и чувственность."
Цена="165" РекомендуемаяРозничнаяЦена="250" РазделКаталогаТоваров="женские"
СписокРазделовКаталогаТоваров="Косметика:Феромоны:женские">
<Описание><![CDATA[Нежный, сладкий и благоухающим ароматом, пробуждает инстинкты и чувственность.]]></Описание>
</Номенклатура>
<Номенклатура id="4833"
Наименование="Natural Instinct Парфюмерная вода мужская "De La Mer " 75 мл"
ОписаниеНоменклатуры="«De La Mer» Легкий и молодежный." Цена="255"
РекомендуемаяРозничнаяЦена="450" РазделКаталогаТоваров="мужские"
СписокРазделовКаталогаТоваров="Косметика:Феромоны:мужские">
<Описание><![CDATA[«De La Mer» Легкий и молодежный.]]></Описание>
</Номенклатура>
<Номенклатура id="4834"
Наименование="Natural Instinct Парфюмерная вода мужская "Triomphateur" 75 мл."
ОписаниеНоменклатуры="«Triomphateur» Динамичный и полный энергии."
Цена="255" РекомендуемаяРозничнаяЦена="450" РазделКаталогаТоваров="мужские"
СписокРазделовКаталогаТоваров="Косметика:Феромоны:мужские">
<Описание><![CDATA[«Triomphateur» Динамичный и полный энергии.]]></Описание>
</Номенклатура>
<Номенклатура id="4961"
Наименование="Мусс для интимной гигиены (L'n'H) 150мл."
ОписаниеНоменклатуры="Это воздушное и деликатное средство для ежедневной гигиены."
Цена="358" РекомендуемаяРозничнаяЦена="895"
СписокРазделовКаталогаТоваров="Косметика:Интимная гигиена"
РазделКаталогаТоваров="Интимная гигиена">
<Описание><![CDATA[Это воздушное и деликатное средство для ежедневной.]]></Описание>
</Номенклатура>
<Номенклатура id="4962"
Наименование="Эмульсия для интимной гигиены (L'n'H) 200мл."
ОписаниеНоменклатуры='"Это прекрасное экономичное средство для ежедневного бережного ухода."'
Цена="346" РекомендуемаяРозничнаяЦена="865" РазделКаталогаТоваров="Интимная гигиена"
СписокРазделовКаталогаТоваров="Косметика:Интимная гигиена">
<Описание><![CDATA["Это прекрасное экономичное средство для ежедневного бережного ухода.]]></Описание>
</Номенклатура>
</Раздел>
</КаталогТоваров>
Элементов <Раздел> может быть несколько, но они не могут быть вложенными друг в друга. Истинная же структура каталога хранится в атрибуте @СписокРазделовКаталогаТоваров. На выходе нужен документ следующего вида
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
<?xml version="1.0" encoding="UTF-8"?>
<eshop id="10022484">
<cat>
<title>Косметика</title>
<descr></descr>
<link>http://example2.ru/store/012/</link>
<cat>
<title>Феромоны</title>
<descr></descr>
<link>http://example2.ru/store/034/</link>
<cat>
<title>женские</title>
<descr></descr>
<link>http://example2.ru/store/05/</link>
<positions>
<pos>
<uid>4679</uid>
<title>Natural Instinct Освежающий тоник для тела Мандарин 95 мл
</title>
<price>250</price>
<price1>0</price1>
<price2>0</price2>
<currency>1</currency>
<amount_left>0</amount_left>
<producer></producer>
<descr>Необыкновенный, свежий, искрящийся цитрусовый аромат.
</descr>
<link>http://example2.ru/store/012345/?pos=4679</link>
</pos>
<pos>
<uid>4680</uid>
<title>Natural Instinct Освежающий тоник для тела Малина 95 мл
</title>
<price>250</price>
<price1>0</price1>
<price2>0</price2>
<currency>1</currency>
<amount_left>0</amount_left>
<producer></producer>
<descr>Нежный, сладкий и благоухающим ароматом, пробуждает
инстинкты и чувственность.</descr>
<link>http://example2.ru/store/012345/?pos=4680</link>
</pos>
</positions>
</cat>
<cat>
<title>мужские</title>
<descr></descr>
<link>http://example2.ru/store/05/</link>
<positions>
<pos>
<uid>4833</uid>
<title>Natural Instinct Парфюмерная вода мужская "De La Mer
" 75 мл</title>
<price>450</price>
<price1>0</price1>
<price2>0</price2>
<currency>1</currency>
<amount_left>0</amount_left>
<producer></producer>
<descr>«De La Mer» Легкий и молодежный.</descr>
<link>http://example2.ru/store/012345/?pos=4833</link>
</pos>
<pos>
<uid>4834</uid>
<title>Natural Instinct Парфюмерная вода мужская
"Triomphateur" 75 мл.</title>
<price>450</price>
<price1>0</price1>
<price2>0</price2>
<currency>1</currency>
<amount_left>0</amount_left>
<producer></producer>
<descr>«Triomphateur» Динамичный и полный энергии.</descr>
<link>http://example2.ru/store/012345/?pos=4834</link>
</pos>
</positions>
</cat>
</cat>
<cat>
<title>Интимная гигиена</title>
<descr></descr>
<link>http://example2.ru/store/78/</link>
<positions>
<pos>
<uid>4961</uid>
<title>Мусс для интимной гигиены (L'n'H) 150мл.</title>
<price>895</price>
<price1>0</price1>
<price2>0</price2>
<currency>1</currency>
<amount_left>0</amount_left>
<producer></producer>
<descr>Это воздушное и деликатное средство для ежедневной гигиены.
</descr>
<link>http://example2.ru/store/012345/?pos=4961</link>
</pos>
<pos>
<uid>4962</uid>
<title>Эмульсия для интимной гигиены (L'n'H) 200мл.</title>
<price>865</price>
<price1>0</price1>
<price2>0</price2>
<currency>1</currency>
<amount_left>0</amount_left>
<producer></producer>
<descr>"Это прекрасное экономичное средство для ежедневного
бережного ухода."</descr>
<link>http://example2.ru/store/012345/?pos=4962</link>
</pos>
</positions>
</cat>
</cat>
</eshop>
Вот xsl-файл преобразования. он пока не формирует корневой тэг e-shop, но не в этом соль:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:key name="ixNom" match="/КаталогТоваров/Раздел/Номенклатура"
use="@СписокРазделовКаталогаТоваров" />
<xsl:key name="NomByPart" match="/КаталогТоваров/Раздел/Номенклатура"
use="substring-before(@СписокРазделовКаталогаТоваров,':')" />
<xsl:variable name="Part" select="/КаталогТоваров/Раздел/Номенклатура
[generate-id(.) = generate-id(key('NomByPart', substring-before(./@СписокРазделовКаталогаТоваров,':')))]" />
<xsl:variable name="catParagraph" select="/КаталогТоваров/Раздел/Номенклатура
[generate-id(.) = generate-id(key('ixNom', ./@СписокРазделовКаталогаТоваров))]" />
<xsl:template match="/">
<html>
<body>
<xsl:for-each select="$Part">
<xsl:sort select="@СписокРазделовКаталогаТоваров" />
<xsl:call-template name="Partitions">
<xsl:with-param name="section" select="./@СписокРазделовКаталогаТоваров" />
</xsl:call-template>
</xsl:for-each>
<xsl:value-of select="count($catParagraph)" />
</body>
</html>
</xsl:template>
<xsl:template match="Номенклатура">
</xsl:template>
<xsl:template name="Partitions">
<xsl:param name="section" />
<xsl:param name="delimeter" select="':'" />
<xsl:param name="currentSection" select="substring-before($section,$delimeter)" />
<xsl:variable name="csL" select="string-length($currentSection)" />
<!-- Чушь. Нужно сделать выборку уникальных подразделов в данном разделе -->
<xsl:variable name="sectionList" select="/КаталогТоваров/Раздел/Номенклатура
[generate-id(.) = generate-id(/КаталогТоваров/Раздел/Номенклатура
[starts-with(@СписокРазделовКаталогаТоваров, concat($currentSection, $delimeter,
substring-before(substring(@СписокРазделовКаталогаТоваров, $csL+2), $delimeter)))])] " />
<xsl:for-each select="$sectionList">
<xsl:variable name="stSection" select="concat($currentSection, $delimeter,
substring-before(substring(@СписокРазделовКаталогаТоваров,$csL+2), $delimeter))" />
<xsl:variable name="endSection" select="substring(@СписокРазделовКаталогаТоваров,$csL+2)" />
<xsl:choose>
<xsl:when test="contains($endSection, $delimeter)">
<xsl:element name="cat">
<xsl:element name="title"><xsl:value-of select="substring-before($endSection, $delimeter)" /></xsl:element>
<descr />
<link>http://sexychel.ru/store/10074723/</link>
<xsl:call-template name="Partitions">
<xsl:with-param name="section" select="substring-after($endSection, $delimeter)" />
<xsl:with-param name="currentSection" select="$stSection" />
</xsl:call-template>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:element name="cat">
<xsl:element name="title"><xsl:value-of select="$endSection" /></xsl:element>
<descr />
<link>http://sexychel.ru/store/10074723/</link>
<xsl:element name="positions">
<xsl:for-each select="/КаталогТоваров/Раздел/Номенклатура
[@СписокРазделовКаталогаТоваров=concat($stSection, $endSection)]">
<xsl:element name="pos">
<uid><xsl:value-of select="@id"/></uid>
<title><xsl:value-of select="@Наименование"/></title>
<price><xsl:value-of select="@РекомендуемаяРозничнаяЦена"/></price>
<price1>0</price1>
<price2>0</price2>
<currency>1</currency>
<amount_left>0</amount_left>
<producer/>
<descr><xsl:value-of select="./Описание"/></descr>
<link>http://sexychel.ru/store/10074723/?pos=<xsl:value-of select="@id"/></link>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Проблема, как мне кажется вот с этой строкой:
1.
2.
3.
4.
<xsl:variable name="sectionList" select="/КаталогТоваров/Раздел/Номенклатура
[generate-id(.) = generate-id(/КаталогТоваров/Раздел/Номенклатура
[starts-with(@СписокРазделовКаталогаТоваров, concat($currentSection, $delimeter,
substring-before(substring(@СписокРазделовКаталогаТоваров, $csL+2), $delimeter)))])] " />
В общем тут нужно, без <xsl:key>, т.к. он не позволяет делать выборку по частичному значению атрибута, выбрать все узлы "Номенклатура" у которых совпадает текущий раздел и разные подразделы на один уровень вниз, без повторений. т.е. группировка.
Уже неделю бьюсь, но результата нет. Кажется, проблема в том, что атрибут @СписокРазделовКаталогаТоваров здесь относится к первому контексту /КаталогТоваров/Раздел/Номенклатура, а нужно взять второй, тот что внутри generate-id