如何使用for-each-group封装XSLT中的元素?

时间:2018-09-04 06:22:53

标签: xml xslt-2.0

我想使用 XSLT

在单个节点调用 COUNTRY 中将 value5转换为value7

示例XML文档-

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

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

我当前正在使用的代码-

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)

在针对root形成模板时遇到了一些问题。

有什么建议吗?

1 个答案:

答案 0 :(得分:1)

您需要为名为root2的元素编写一个模板,并确保通过身份转换模板来处理其余部分:

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

XSLT和XQuery都无需硬编码<country>...</country>形式的文字结果元素,而是允许您基于表达式创建元素,而在XSLT中使用例如<xsl:element name="{expression}">...</xsl:element>,在XQuery element {expression} {...}中。因此,您当然可以像在https://xsltfiddle.liberty-development.net/gWmuiJJ/0https://xsltfiddle.liberty-development.net/gWmuiJJ/1https://xsltfiddle.liberty-development.net/gWmuiJJ/2

中那样声明全局参数

,例如

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

并使用它

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