Как обернуть элементы в XSLT, используя for-each-group? - PullRequest
0 голосов
/ 04 сентября 2018

Я хочу обернуть значение 5 в значение 7 в одном вызове узла СТРАНА с использованием XSLT

Пример 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 голосов
/ 04 сентября 2018

Вам необходимо написать шаблон для элемента с именем 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>

Вместо жесткого кодирования буквального элемента результата в виде <country>...</country> и XSLT, и XQuery позволяют создавать элемент на основе выражения, в XSLT вы используете, например, например. <xsl:element name="{expression}">...</xsl:element>, в XQuery element {expression} {...}. Поэтому вы, безусловно, можете объявить что-то вроде глобального параметра, как это сделано в https://xsltfiddle.liberty -development.net / gWmuiJJ / 0 , https://xsltfiddle.liberty -development.net / gWmuiJJ / 1 , https://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>
...