Сопоставление и слияние в XSLT 1.0

У меня есть образец XML-сообщения, которое содержит несколько родительских узлов. Требование похоже на то, что если два родительских узла одинаковы, объедините дочерний узел.

Образец входного сообщения

<document>
<party>
    <gtin>1000909090</gtin>
    <pos>
        <attrGroupMany name="temperatureInformation">
            <row>
                <attr name="temperatureCode">STORAGE</attr>
                <attrQualMany name="temperature">
                    <value qual="FAH">10</value>
                    <value qual="CC">20</value>
                </attrQualMany>
                <attrGroupMany name="temperatureStats">
                    <row>
                        <attr name="StatsCode">CODE1</attr>
                    </row>
                    <row>
                        <attr name="StatsCode">CODE2</attr>
                    </row>
                </attrGroupMany>
            </row>
            <row>
                <attr name="temperatureCode">STORAGE</attr>
                <attrQualMany name="temperature">
                    <value qual="FAH">10</value>
                    <value qual="CC">20</value>
                </attrQualMany>
                <attrGroupMany name="temperatureStats">
                    <row>
                        <attr name="StatsCode">CODE3</attr>
                    </row>
                    <row>
                        <attr name="StatsCode">CODE4</attr>
                    </row>
                </attrGroupMany>
            </row>
            <row>
                <attr name="temperatureCode">HANDLING</attr>
                <attrQualMany name="temperature">
                    <value qual="FAH">10</value>                    
                </attrQualMany>
                <attrGroupMany name="temperatureStats">
                    <row>
                        <attr name="StatsCode">CODE5</attr>
                    </row>
                    <row>
                        <attr name="StatsCode">CODE6</attr>
                    </row>
                </attrGroupMany>
            </row>
            <row>
                <attr name="temperatureCode">HANDLING</attr>
                <attrGroupMany name="temperatureStats">
                    <row>
                        <attr name="StatsCode">CODE7</attr>
                    </row>
                    <row>
                        <attr name="StatsCode">CODE8</attr>
                    </row>
                </attrGroupMany>
            </row>
        </attrGroupMany>
    </pos>
</party>
</document>

нам нужно объединить значение temperatureCode, все значения температуры (если они есть) для всех строк, и если они дублируются, то объединить строку внутри TemperatureStats дочернего элемента в родительском.

Ожидаемый результат находится в той же структуре. Вы можете видеть, что второй узел объединен с первым

<document>
<party>
    <gtin>1000909090</gtin>
    <pos>
        <attrGroupMany name="temperatureInformation">
            <row>
                <attr name="temperatureCode">STORAGE</attr>
                <attrQualMany name="temperature">
                    <value qual="FAH">10</value>
                    <value qual="CC">20</value>
                </attrQualMany>
                <attrGroupMany name="temperatureStats">
                    <row>
                        <attr name="StatsCode">CODE1</attr>
                    </row>
                    <row>
                        <attr name="StatsCode">CODE2</attr>
                    </row>
                    <row>
                        <attr name="StatsCode">CODE3</attr>
                    </row>
                    <row>
                        <attr name="StatsCode">CODE4</attr>
                    </row>
                </attrGroupMany>
            </row>
            <row>
                <attr name="temperatureCode">HANDLING</attr>
                <attrQualMany name="temperature">
                    <value qual="FAH">10</value>                    
                </attrQualMany>
                <attrGroupMany name="temperatureStats">
                    <row>
                        <attr name="StatsCode">CODE5</attr>
                    </row>
                    <row>
                        <attr name="StatsCode">CODE6</attr>
                    </row>
                </attrGroupMany>
            </row>
            <row>
                <attr name="temperatureCode">HANDLING</attr>
                <attrGroupMany name="temperatureStats">
                    <row>
                        <attr name="StatsCode">CODE7</attr>
                    </row>
                    <row>
                        <attr name="StatsCode">CODE8</attr>
                    </row>
                </attrGroupMany>
            </row>
        </attrGroupMany>
    </pos>
</party>
</document>

Любой вклад будет очень ценным.


person Victor    schedule 08.07.2016    source источник
comment
Отличается ли группировка, в которой вы нуждаетесь, от ваших предыдущих вопросов? Если вы хотите объединить некоторые элементы и использовать мюнхианскую группировку с ключом, тогда key('key-name', someKeyValueExpression)/attrGroupMany[@name = 'temperatureStats']/row даст вам все row элементы, которые вы хотите объединить. Использование ключа для группировки кажется ответом на предыдущие вопросы.   -  person Martin Honnen    schedule 08.07.2016
comment
Как позаботиться о необязательных узлах ‹attrQualMany name=temperature› и как я могу напечатать весь xml в выводе. есть ли какая-нибудь команда копирования, которую я могу использовать? Если вы окажете помощь в предоставлении образца XSLT, было бы здорово.   -  person Victor    schedule 08.07.2016


Ответы (1)


Я думаю, у вас есть решение для группировки в предыдущем ответе https://stackoverflow.com/a/38240246/252228, затем вы можете обрабатывать элементы в группе, вызывая ключевую функцию:

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

    <xsl:output indent="yes"/>


    <xsl:key name="group" match="attrGroupMany[@name = 'temperatureInformation']/row"
        use="concat(attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature'])"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="attrGroupMany[@name = 'temperatureInformation']">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates select="row[generate-id() = generate-id(key('group', concat(attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature']))[1])]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="attrGroupMany[@name = 'temperatureStats']">
        <xsl:copy>
            <xsl:apply-templates select="@* | key('group', concat(../attr[@name = 'temperatureCode'], '|', ../attrQualMany[@name = 'temperature']))/attrGroupMany[@name = 'temperatureStats']/row"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

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

person Martin Honnen    schedule 08.07.2016
comment
Это работает. Спасибо. Эта проблема является частью более крупной проблемы, над которой я пытаюсь работать. Этот образец обязательно поможет. - person Victor; 08.07.2016
comment
Мартин. Нужна ваша помощь для другого набора вопросов. Не могли бы вы помочь? Спасибо stackoverflow.com/questions/38993864/ - person Victor; 17.08.2016