Несмотря на то, что есть несколько тем, объясняющих использование нескольких шаблонов в одном файле xslt, я не могу найти решение моей проблемы.
Я хотел бы применить два преобразования к моему XML-файлу. Во-первых, я хочу сделать группировку по идентификатору. Затем я хотел бы выполнить некоторую обработку, чтобы удалить специальные символы.
По отдельности шаблоны работают нормально, но когда я пытаюсь их собрать вместе, у меня выводится xml и текстовый результат. Моя цель — иметь в выводе только текстовую часть и сохранять XML-часть только в качестве промежуточного шага.
Не могли бы вы рассказать мне, как правильно использовать атрибут режима? Я хотел бы сделать что-то похожее на это
<xsl:template match = "">
<xsl:apply-templates select = "XML_Part"/> ---> hide from the final output
<xsl:apply-templates select = "Text_Part"/>
</xsl:template>
<xsl:template match = "" mode = "XML_Part">
</xsl:template>
<xsl:template match = "" mode = "Text_Part">
</xsl:template>
XML-файл (входной)
<?xml version = "1.0" encoding = "UTF-8"?>
<wd:Report_Data xmlns:wd = "http://www.workday.org/">
<wd:Report_Entry>
<wd:id>1000</wd:id>
<wd:name>Call-of-Duty</wd:name>
<wd:price>50.12</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>1000</wd:id>
<wd:name>Call-of-Duty</wd:name>
<wd:price>60.0</wd:price>
<wd:copy>1</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>2000</wd:id>
<wd:name>Metal Slug</wd:name>
<wd:price>75.00</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>3000</wd:id>
<wd:name>Need For Speed</wd:name>
<wd:price>40.00</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
</wd:Report_Data>
XSLT-шаблон для группировки
<xsl:template match = "/wd:Report_Data">
<xsl:copy>
<xsl:for-each-group select = "wd:Report_Entry" group-by = "wd:id">
<xsl:copy>
<xsl:copy-of select = "wd:id"/>
<xsl:copy-of select = "wd:name"/>
<wd:price>
<xsl:value-of select = "sum(current-group()/wd:price)" />
</wd:price>
<xsl:copy-of select = "wd:copy"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
XSLT для удаления специальных символов и отображения текстовой части
<xsl:template match = "wd:Report_Data/wd:Report_Entry">
<xsl:value-of select = "wd:id"/>
<xsl:text>|</xsl:text>
<xsl:value-of select = "translate(wd:name,'-',' ')"/>
<xsl:text>|</xsl:text>
<xsl:value-of select = "wd:price"/>
<xsl:text>|</xsl:text>
<xsl:value-of select = "wd:copy"/>
</xsl:template>
Текущий выход
<wd:Report_Data xmlns:wd = "http://www.workday.org/">
<wd:Report_Entry>
<wd:id>1000</wd:id>
<wd:name>Call of Duty</wd:name>
<wd:price>110.12</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>2000</wd:id>
<wd:name>Metal Slug</wd:name>
<wd:price>75</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
<wd:Report_Entry>
<wd:id>3000</wd:id>
<wd:name>Need For Speed</wd:name>
<wd:price>40</wd:price>
<wd:copy>0</wd:copy>
</wd:Report_Entry>
</wd:Report_Data>
1000|Call of Duty|110.12|0
2000|Metal Slug|75.00|0
3000|Need For Speed|40.00|0
Ожидаемый результат
1000|Call of Duty|110.12|0
2000|Metal Slug|75.00|0
3000|Need For Speed|40.00|0
Нет необходимости связывать преобразования в цепочку. Вы можете сделать все это сразу, просто:
<xsl:stylesheet version = "2.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:wd = "http://www.workday.org/" >
<xsl:output method = "text"/>
<xsl:template match = "/wd:Report_Data">
<xsl:for-each-group select = "wd:Report_Entry" group-by = "wd:id">
<xsl:value-of select = "wd:id, translate(wd:name, '-', ' '), sum(current-group()/wd:price), wd:copy" separator = "|"/>
<xsl:text> </xsl:text>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Если вам нужно, чтобы цена была отформатирована, как показано, измените:
sum(current-group()/wd:price)
к:
format-number(sum(current-group()/wd:price), '0.00')
Если вы хотите объединить преобразования (несмотря на то, что @y.arazim узнал, что в этом случае вам это не нужно), общая схема такова:
<xsl:variable name = "temp">
<xsl:apply-templates mode = "phase1"/>
</xsl:variable>
<xsl:apply-templates select = "$temp" mode = "phase2"/>
И затем, конечно, прикрепите mode = "phase1"
к шаблонам этапа 1 и mode = "phase2"
к шаблонам этапа 2 — в идеале также поместите их в разные модули таблиц стилей.