XSL мюнхенская группировка - и фильтрация
Сценарий таков: у меня есть магазин, в котором продается мебель от двух производителей, CompanyA и CompanyB, а также импортная мебель от одного импортера, CompanyC.
Мой файл выглядит так
<shop>
<product>
<name>Chair</name>
<colour>Green</colour>
<producer>CompanyA</producer>
</product>
<product>
<name>Chair</name>
<colour>Green</colour>
<producer>CompanyB</producer>
</product>
<product>
<name>Chair</name>
<colour>Blue</colour>
<producer>CompanyA</producer>
</product>
<product>
<name>Chair</name>
<colour>Blue</colour>
<importer>CompanyC</importer>
</product>
<product>
<name>Table</name>
<colour>Green</colour>
<importer>CompanyC</importer>
</product>
<product>
<name>Table</name>
<colour>Green</colour>
<producer>CompanyA</producer>
</product>
<product>
<name>Table</name>
<colour>Blue</colour>
<producer>CompanyB</producer>
</product>
<product>
<name>Table</name>
<colour>Blue</colour>
<importer>CompanyC</importer>
</product>
</shop>
Я хочу уменьшить свой запас, поэтому мне нужен список аналогичных продуктов от CompanyA и CompanyC. Я не хочу перечислять похожие продукты от CompanyA и CompanyB, и при этом я не хочу список похожих продуктов от CompanyB и CompanyC. Желаемый вывод это
<shop>
<product>
<name>Chair</name>
<colour>Blue</colour>
<producer>CompanyA</producer>
</product>
<product>
<name>Chair</name>
<colour>Blue</colour>
<importer>CompanyC</importer>
</product>
<product>
<name>Table</name>
<colour>Green</colour>
<importer>CompanyC</importer>
</product>
<product>
<name>Table</name>
<colour>Green</colour>
<producer>CompanyA</producer>
</product>
</shop>
Я скопировал копию старой таблицы стилей, которая дает мне список всех аналогичных продуктов, поэтому моя проблема заключается в следующем: как я могу отфильтровать список, чтобы он давал только пары, из которых одна получена из CompanyA, а другая - из CompanyC?
Я могу использовать только XSL 1.0 без расширений
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="no"/>
<xsl:key name="duplo" match="product" use="concat(name,colour)"/>
<xsl:template match="/">
<shop>
<xsl:for-each select="//product[generate-id(.)=generate-id(key('duplo', concat(name,colour))[2])]">
<xsl:for-each select="key('duplo', concat(name,colour))">
<product>
<name><xsl:value-of select="name"/></name>
<colour><xsl:value-of select="colour"/></colour>
<producer><xsl:value-of select="producer"/></producer>
<importer><xsl:value-of select="importer"/></importer>
</product>
</xsl:for-each>
</xsl:for-each>
</shop>
</xsl:template>
</xsl:stylesheet>
1 ответ
Один из способов сделать это - вложить свой существующий xsl:for-each
в xsl:if
состояние
<xsl:if test="key('duplo', concat(name,colour))[producer = 'CompanyA'] and key('duplo', concat(name,colour))[importer = 'CompanyC']">
<xsl:for-each select="key('duplo', concat(name,colour))[producer = 'CompanyA' or importer = 'CompanyC']">
<product>
<name><xsl:value-of select="name"/></name>
<colour><xsl:value-of select="colour"/></colour>
<producer><xsl:value-of select="producer"/></producer>
<importer><xsl:value-of select="importer"/></importer>
</product>
</xsl:for-each>
</xsl:if>
Вы можете уменьшить размер выражений, используя переменные, возможно. Например
<xsl:variable name="group" select="key('duplo', concat(name,colour))" />
<xsl:variable name="A" select="$group[producer = 'CompanyA']" />
<xsl:variable name="B" select="$group[importer = 'CompanyC']" />
<xsl:if test="$A and $B">
<xsl:for-each select="$A|$B">
<product>
<name><xsl:value-of select="name"/></name>
<colour><xsl:value-of select="colour"/></colour>
<producer><xsl:value-of select="producer"/></producer>
<importer><xsl:value-of select="importer"/></importer>
</product>
</xsl:for-each>
</xsl:if>