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