XSLT / связать элементы с группой - PullRequest
0 голосов
/ 16 октября 2019

Еще один вопрос XSLT / Grouping, но я не смог найти ответ на этот поворот. Я знаю, как выполнить мюенихскую группировку, но у меня проблемы с попыткой связать контент подэлементов, принадлежащий любому из сгруппированных элементов в той группе, к которой относится этот родительский элемент.

Идея заключается в том, что элементы сгруппированы по комбинации содержимого и цвета, поэтому в этом примере файла будет сгенерировано 4 различных комбинации. Для этих групп цены рассчитываются вместе внутри группы. Некоторые из товарных линий включают в себя некоторые дополнительные функции, которые затем должны быть сопоставлены с правильной группой, и в этом проблема ...

Эти дополнительные строки нужно читать отдельно как "нулевые строки", и онидолжен иметь номер, который ссылается на «номер группы», сгенерированный XSL

Я пытался создать предшествующий брат, чтобы соответствовать этой группе, но я только заставляю его работать в исходных позициях, а не в группах

XML-образец

<shipment>
    <goodslines>
        <goodsline>
            <content>content1</content>
            <color>color1</color>
            <price>10</price>
            <extras>
                <extra>extra-a</extra>
                <price>5</price>
            </extras>
        </goodsline>
        <goodsline>
            <content>content1</content>
            <color>color1</color>
            <price>10</price>
        </goodsline>
        <goodsline>
            <content>content2</content>
            <color>color1</color>
            <price>20</price>
            <extras>
                <extra>extra-b</extra>
                <price>15</price>
            </extras>
        </goodsline>
        <goodsline>
            <content>content2</content>
            <color>color1</color>
            <price>20</price>
            <extras>
                <extra>extra-c</extra>
                <price>25</price>
            </extras>
        </goodsline>
        <goodsline>
            <content>content2</content>
            <color>color2</color>
            <price>25</price>
        </goodsline>
        <goodsline>
            <content>content3</content>
            <color>color1</color>
            <price>30</price>
        </goodsline>
        <goodsline>
            <content>content3</content>
            <color>color1</color>
            <price>30</price>
        </goodsline>
    </goodslines>
</shipment>

XSL (1.0):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    <xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:template match="/">
        <xsl:call-template name="Package"/>
    </xsl:template>
    <xsl:key name="GoodsLine" match="//goodsline" use="concat(content, '|', color)"/>
    <xsl:key name="Extra" match="//extras" use="extra"/>
    <xsl:template name="Package">
        <xsl:for-each select="/shipment/goodslines/goodsline[generate-id()=generate-id(key('GoodsLine',concat(content, '|', color)))]">
            <xsl:value-of select="position()" />
            <xsl:text>§</xsl:text>
            <xsl:value-of select="content"/>
            <xsl:text>§</xsl:text>
            <xsl:value-of select="sum(key('GoodsLine', concat(content, '|', color))/price)"/>
            <xsl:text>&#xD;</xsl:text>
        </xsl:for-each>

        <xsl:for-each select="/shipment/goodslines/goodsline/extras">
            <xsl:text>0§</xsl:text>
            <xsl:value-of select="../content"/>
            <xsl:text>§</xsl:text>
            <xsl:value-of select="price"/>
            <xsl:text>§</xsl:text>
            <xsl:value-of select="extra"/>
            <xsl:text>§</xsl:text>
            <xsl:value-of select="count(../preceding-sibling::goodsline[generate-id()=generate-id(key('GoodsLine',concat(content, '|', color)))])+1 "/>
            <xsl:text>&#xD;</xsl:text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Желаемый результат будет:

1§content1§20
2§content2§40
3§content2§25
4§content3§60
0§content1§5§extra-a§1
0§content2§15§extra-b§2
0§content2§25§extra-c§2

where the format is:

GroupNo§Content§GroupPriceSum§

and for extras:

Zero§Content§ExtraPrice§ExtraName§GroupBelongTo

Так, что последнее число из нихдополнительные строки указывают, к какой группе принадлежит.

Теперь я получаю:

1§content1§20
2§content2§40
3§content2§25
4§content3§60
0§content1§5§extra-a§1
0§content2§15§extra-b§2
0§content2§25§extra-c§3

Где последняя идет не так. Последняя строка должна принадлежать группе «content2 / color1», как эта extra-b. Попытка переместить эти дополнительные строки между различными goodsline-элементами и / или добавить их приведет к тому, что результат будет более или менее неудачным. Что-то не так в моем мышлении prceding-sibling, но что это?

И да, я могу использовать только XSLT 1.0

1 Ответ

1 голос
/ 16 октября 2019

Я бы посоветовал вам попробовать это следующим образом:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8"/>

<xsl:key name="line" match="goodsline" use="concat(content, '|', color)"/>

<xsl:template match="/shipment">
    <!-- distinct elements -->
    <xsl:variable name="groups" select="goodslines/goodsline[generate-id()=generate-id(key('line',concat(content, '|', color)))]"/>
    <!-- goods -->
    <xsl:for-each select="$groups">
        <xsl:value-of select="position()" />
        <xsl:text>§</xsl:text>
        <xsl:value-of select="content"/>
        <xsl:text>§</xsl:text>
        <xsl:value-of select="sum(key('line', concat(content, '|', color))/price)"/>
        <xsl:text>&#xD;</xsl:text>
    </xsl:for-each>
    <!-- extras -->
    <xsl:for-each select="$groups">
        <xsl:variable name="group-number" select="position()" />
        <!-- extras in this group -->
        <xsl:for-each select="key('line', concat(content, '|', color))/extras">
            <xsl:text>0§</xsl:text>
            <xsl:value-of select="../content"/>
            <xsl:text>§</xsl:text>
            <xsl:value-of select="price"/>
            <xsl:text>§</xsl:text>
            <xsl:value-of select="extra"/>
            <xsl:text>§</xsl:text>
            <xsl:value-of select="$group-number"/>
            <xsl:text>&#xD;</xsl:text>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

Это сохраняет отдельные группы в переменную, затем обрабатывает переменную дважды -один раз для самих групп и один раз для их статистов. Таким образом, вы получаете один и тот же номер группы на каждом проходе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...