简体   繁体   English

分组后的XSLT 1.0条件合并

[英]XSLT 1.0 conditional merge after grouping

My input xml looks as shown below: 我的输入xml如下所示:

<items>
    <item>
        <geoDetails>
            <street>xxx</street>
            <city>yyy</city>
            <state>zzz</state>
        </geoDetails>
        <otherDetails>
            <desc>abcd111</desc>
            <comments>good item</comments>
        </otherDetails>
        <key>
            <name>item1</name>
            <id>123</id>
            <color>red</color>
        </key>
        <misc>
            <available>false</available>
            <details>geo</details>
        </misc>
    </item>
    <item>
        <otherDetails>
            <desc>efgh222</desc>
            <comments>good item</comments>
        </otherDetails>
        <key>
            <name>item2</name>
            <id>123</id>
            <color>red</color>
        </key>
        <misc>
            <available>false</available>
            <details>other</details>
        </misc>
    </item>
    <item>
        <geoDetails>
            <street>ppp</street>
            <city>qqq</city>
            <state>rrr</state>
        </geoDetails>
        <otherDetails>
            <desc>ijkl333</desc>
            <comments>best item</comments>
        </otherDetails>
        <key>
            <name>item3</name>
            <id>456</id>
            <color>blue</color>
        </key>
        <misc>
            <available>false</available>
            <details>other</details>
        </misc>
    </item>
</items>

The key for grouping 'item' nodes is concat(/items/item/key/id,/items/item/key/color) For each identified group, merge should happen with the logic as given below: 对“ item”节点进行分组的关键是concat(/ items / item / key / id,/ items / item / key / color)对于每个已标识的组,合并应使用以下给出的逻辑进行:

a. 一种。 Extract 'geoDetails' from the 'item' where misc/details is 'geo'. 从其他/细节为“ geo”的“项目”中提取“ geoDetails”。

b. b。 Extract 'otherDetails' from the 'item' where misc/details is 'other'. 从其他/细节为“其他”的“项目”中提取“其他细节”。 Only one misc/details is present in each 'item' with the value of either 'geo' or 'other'. 每个“项目”中只有一个杂项/详细信息,其值为“ geo”或“ other”。

c. C。 Extract the 'key' element from the first 'item' in a given group. 从给定组的第一个“项目”中提取“关键”元素。

d. d。 The 'misc' element should contain 'available' element as it is (this is always 'false' and hence populating this once is enough) and the 'details' element should have value based on the element 'geoDetails' or 'otherDetails' populated through the logic as given in steps a & b above. “ misc”元素应按原样包含“ available”元素(始终为“ false”,因此填充一次就足够了),并且“ details”元素应具有基于填充的元素“ geoDetails”或“ otherDetails”的值通过上面步骤a和b中给出的逻辑。 There should be 2 'details' elements if both the 'geoDetails' and 'otherDetails' are populated. 如果同时填充了“ geoDetails”和“ otherDetails”,则应有2个“ details”元素。

e. e。 Any other single 'item' element that is which is not part of a group should be pushed to output as it is. 不属于组的任何其他单个“ item”元素应按原样输出。

And the expected output based on above logic is as shown below: 基于上述逻辑的预期输出如下所示:

<items>
<item>
    <geoDetails>
        <street>xxx</street>
        <city>yyy</city>
        <state>zzz</state>
    </geoDetails>
    <otherDetails>
        <desc>efgh222</desc>
        <comments>good item</comments>
    </otherDetails>
    <key>
        <name>item1</name>
        <id>123</id>
        <color>red</color>
    </key>
    <misc>
        <available>false</available>
        <details>geo</details>
        <details>other</details>
    </misc>
</item>
<item>
    <geoDetails>
        <street>ppp</street>
        <city>qqq</city>
        <state>rrr</state>
    </geoDetails>
    <otherDetails>
        <desc>ijkl333</desc>
        <comments>best item</comments>
    </otherDetails>
    <key>
        <name>item3</name>
        <id>456</id>
        <color>blue</color>
    </key>
    <misc>
        <available>false</available>
        <details>other</details>
    </misc>
</item>

I tried the transformation based on Muenchian grouping using xsl:key and apply-templates. 我使用xsl:key和apply-templates尝试了基于Muenchian分组的转换。 I was able to group the 'item' elements but couldn't proceed further on how to merge these grouped elements based on the above set of conditions. 我能够对'item'元素进行分组,但是无法根据上述条件进一步讨论如何合并这些分组的元素。

XSLT Transformation: XSLT转换:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" version="1.0" exclude-result-prefixes="exsl">
<xsl:key match="item" name="itemKey" use="concat(key/id,key/color)" />
<xsl:template match="/">
    <xsl:variable name="output">
        <xsl:apply-templates />
    </xsl:variable>
    <xsl:copy-of select="exsl:node-set($output)/*" />
</xsl:template>
<!-- default template -->
<xsl:template match="node( ) | @*">
    <xsl:copy>
        <xsl:apply-templates select="@*" />
        <xsl:apply-templates />
    </xsl:copy>
</xsl:template>
<xsl:template match="item[generate-id(.)=generate-id(key('itemKey',concat(key/id,key/color))[1])]">
    <xsl:copy>
        <xsl:apply-templates select="@* | key('itemKey',concat(key/id,key/color))/node()" />
    </xsl:copy>
</xsl:template>
<xsl:template match="item" />

I've gone through several related questions on Stackoverflow but couldn't adapt the merging process to my current scenario. 我在Stackoverflow上经历了几个相关的问题,但是无法使合并过程适应当前的情况。 Any help is greatly appreciated. 任何帮助是极大的赞赏。

AFAICT, this satisfies your conditions (as far as I was able to understand them): AFAICT,这可以满足您的条件(据我所知):

XSLT 1.0 XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="itemKey" match="item" use="concat(key/id, key/color)" />

<xsl:template match="/items">
    <xsl:copy>
        <xsl:apply-templates select="item[generate-id()=generate-id(key('itemKey', concat(key/id, key/color))[1])]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="item">
    <xsl:variable name="curr-group" select="key('itemKey', concat(key/id, key/color))" />
    <xsl:choose>
        <!-- e. Any other single 'item' element that is which is not part of a group should be pushed to output as it is. -->
        <xsl:when test="count($curr-group)=1">
            <xsl:copy-of select="."/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy>
                <!-- a. Extract 'geoDetails' from the 'item' where misc/details is 'geo'. --> 
                <xsl:copy-of select="$curr-group[misc/details='geo']/geoDetails"/>
                <!-- b. Extract 'otherDetails' from the 'item' where misc/details is 'other'. --> 
                <xsl:copy-of select="$curr-group[misc/details='other']/otherDetails"/>
                <!-- c. Extract the 'key' element from the first 'item' in a given group. -->
                <xsl:copy-of select="key"/>
                <!-- d. ??? --> 
                <misc>
                    <available>false</available>
                    <xsl:copy-of select="$curr-group/misc/details"/>
                </misc>
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>   
</xsl:template>

</xsl:stylesheet>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM