分组后XSLT 1.0条件合并(XSLT 1.0 conditional merge after grouping)

编程入门 行业动态 更新时间:2024-10-26 20:31:46
分组后XSLT 1.0条件合并(XSLT 1.0 conditional merge after grouping)

我的输入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>

用于对“项目”节点进行分组的关键是concat(/ items / item / key / id,/ items / item / key / color)对于每个标识的组,合并应该按照下面给出的逻辑进行:

一个。 从'item'中提取'geoDetails',其中misc / details是'geo'。

湾 从'item'中提取'otherDetails',其中misc / details是'other'。 每个'item'中只有一个misc / details带有'geo'或'other'的值。

C。 从给定组中的第一个“项目”中提取“key”元素。

d。 'misc'元素应该包含'available'元素(这总是'false',因此填充一次就足够了)'details'元素应该具有基于元素'geoDetails'或'otherDetails'填充的值通过上面步骤a和b给出的逻辑。 如果填充了'geoDetails'和'otherDetails',则应该有2个'details'元素。

即 任何其他不属于组的单个“item”元素都应按原样推送到输出。

基于上述逻辑的预期输出如下所示:

<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>

我尝试使用xsl:key和apply-templates基于Muenchian分组进行转换。 我能够对“项目”元素进行分组,但无法进一步了解如何根据上述条件合并这些分组元素。

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" />

我在Stackoverflow上经历了几个相关的问题,但无法使合并过程适应我当前的场景。 任何帮助是极大的赞赏。

My input xml looks as shown below:

<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:

a. Extract 'geoDetails' from the 'item' where misc/details is 'geo'.

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'.

c. Extract the 'key' element from the first 'item' in a given group.

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. There should be 2 'details' elements if both the 'geoDetails' and 'otherDetails' are populated.

e. Any other single 'item' element that is which is not part of a group should be pushed to output as it is.

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. 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.

XSLT Transformation:

<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. Any help is greatly appreciated.

最满意答案

AFAICT,这满足您的条件(据我所知):

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>

AFAICT, this satisfies your conditions (as far as I was able to understand them):

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>

更多推荐

key,'item',<xsl,xsl,电脑培训,计算机培训,IT培训"/> <meta name=&q

本文发布于:2023-07-21 09:38:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1209013.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:条件   XSLT   grouping   merge   conditional

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!