How to WRAP the elements in XSLT using for-each-group?

随声附和 提交于 2019-12-24 21:17:07

问题


I want to Wrap value5 to value7 in a single node call COUNTRY using XSLT

Example XML Document-

<root>
  <root1>
    <root2>
     <value1>somevalue</value1>
     <value2>somevalue</value2>
     <value3>somevalue</value3>
     <value4>somevalue</value4>
     <value5>Australia</value5>
     <value6>India</value6>
     <value7>USA</value7>
     <value8>somevalue</value8>
     <value9>somevalue</value9>
     <value10>somevalue</value10>
   </root2>
  </root1>
</root>

Output XML-

<root>
  <root1>
    <root2>
     <value1>somevalue</value1>
     <value2>somevalue</value2>
     <value3>somevalue</value3>
     <value4>somevalue</value4>
     <COUNTRY>
       <value5>Australia</value5>
       <value6>India</value6>
       <value7>USA</value7>
     </COUNTRY>
     <value8>somevalue</value8>
     <value9>somevalue</value9>
     <value10>somevalue</value10>
   </root2>
  </root1>
</root>

Code i am using currently-

xquery version "1.0-ml";
declare variable $doc := document {
 <root>
  <root1>
    <root2>
     <value1>somevalue</value1>
     <value2>somevalue</value2>
     <value3>somevalue</value3>
     <value4>somevalue</value4>
     <value5>Australia</value5>
     <value6>India</value6>
     <value7>USA</value7>
     <value8>somevalue</value8>
     <value9>somevalue</value9>
     <value10>somevalue</value10>
   </root2>
  </root1>
</root>
};

declare variable $grouping-xslt := <xsl:stylesheet version="2.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />

<xsl:template match="root">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="not(self::value5 | self::value6 | self::value7)">
            <xsl:choose>
                <xsl:when test="current-grouping-key()">
                    <xsl:copy-of select="current-group()"/>
                </xsl:when>
                <xsl:otherwise>
                    <country>
                        <xsl:copy-of select="current-group()"/>
                    </country>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>        
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>;

xdmp:xslt-eval($grouping-xslt, $doc)

I am having some issues while forming template with respect to root.

Any Suggestions?


回答1:


You need to write a template for the element named root2 and make sure you handle the rest by the identity transformation template:

<xsl:stylesheet version="2.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />

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

<xsl:template match="root2">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="not(self::value5 | self::value6 | self::value7)">
            <xsl:choose>
                <xsl:when test="current-grouping-key()">
                    <xsl:copy-of select="current-group()"/>
                </xsl:when>
                <xsl:otherwise>
                    <country>
                        <xsl:copy-of select="current-group()"/>
                    </country>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>        
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Instead of hard coding a literal result element in the form of <country>...</country> both XSLT and XQuery allow you to create an element based on an expression, in XSLT you use e.g. <xsl:element name="{expression}">...</xsl:element>, in XQuery element {expression} {...}. So you can certainly declare something like a global parameter as done in https://xsltfiddle.liberty-development.net/gWmuiJJ/0, https://xsltfiddle.liberty-development.net/gWmuiJJ/1, https://xsltfiddle.liberty-development.net/gWmuiJJ/2

, e.g.

  <xsl:param name="wrapper-name" 
    select="if (/* instance of element(biology))
            then 'fruits'
            else if (/* instance of element(geography))
            then 'countries'
            else 'wrapper'"/>

and use it

                    <xsl:element name="{$wrapper-name}">
                        <xsl:copy-of select="current-group()"/>
                    </xsl:element>


来源:https://stackoverflow.com/questions/52159957/how-to-wrap-the-elements-in-xslt-using-for-each-group

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!