XSLT:将相邻元素与同类分组

发布于 2025-02-13 10:33:45 字数 2210 浏览 3 评论 0原文

我是XSLT的新手,我陷入了“相邻元素”问题上。 我的XML输入遵循架构:

<body>
<aside class="1">
   some tags + text
</aside>
<aside class="2">
    some tags + text
</aside>
<aside class="2">
    some tags + text
</aside>
<p>...</p>
<img .../>
<aside class="2">
    some tags + text
</aside>
<aside class="2">
    some tags + text
</aside>
</body>

我需要的(也无法实现)是一个输出,其中相邻 旁边将同一类分组在一起。当之无愧的输出就是这样:

<body>
<tag1 class="1">everything contained in the grouped tags</tag1>
<tag2 class="2">everything contained in the grouped tags</tag2>

<p>...</p>
<img.../>

<tag2 class="2">everything contained in the grouped tags</tag2>
</body>

可以使用变量来管理新标签,这很好。但是如何获得此输出?到目前为止,我已经获得了最好的结果:

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

<xsl:template match="body">
     <xsl:for-each-group select="aside" group-adjacent="@class">
        <xsl:variable name="grouping_tag">
           <xsl:choose>
               <xsl:when test="@class = '1'">tag1</xsl:when>
               <xsl:when test="@class = '2'">tag2</xsl:when>
               <xsl:otherwise>tagX</xsl:otherwise>
           </xsl:choose>
       </xsl:variable>
       <xsl:element name="{$grouping_tag}" >
            <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute>
            <xsl:for-each select="current-group()/*">                    
                <xsl:copy>
                    <xsl:apply-templates select="@*"/>
                    <xsl:apply-templates/>
                </xsl:copy>
            </xsl:for-each> 
       </xsl:element>           
     </xsl:for-each-group>

</xsl:template>

此解决方案确实确实将相邻的与同一类分组,但是在输出中,我丢失了其中未包含的所有内容(例如,<代码> pimg)。我需要在其他所有位置上进行其他一切。

有人可以帮我吗?

I'm new to XSLT and I'm stuck on the "grouping adjacent elements" problem.
My XML input follows the schema:

<body>
<aside class="1">
   some tags + text
</aside>
<aside class="2">
    some tags + text
</aside>
<aside class="2">
    some tags + text
</aside>
<p>...</p>
<img .../>
<aside class="2">
    some tags + text
</aside>
<aside class="2">
    some tags + text
</aside>
</body>

What I need (and can't achieve) is an output in which the adjacent aside with the same class are grouped together. The desidered output would be like this:

<body>
<tag1 class="1">everything contained in the grouped tags</tag1>
<tag2 class="2">everything contained in the grouped tags</tag2>

<p>...</p>
<img.../>

<tag2 class="2">everything contained in the grouped tags</tag2>
</body>

The new tags can be managed using variables, and that's fine. But how do I obtain this output? So far, I've obtained the best results with this:

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

<xsl:template match="body">
     <xsl:for-each-group select="aside" group-adjacent="@class">
        <xsl:variable name="grouping_tag">
           <xsl:choose>
               <xsl:when test="@class = '1'">tag1</xsl:when>
               <xsl:when test="@class = '2'">tag2</xsl:when>
               <xsl:otherwise>tagX</xsl:otherwise>
           </xsl:choose>
       </xsl:variable>
       <xsl:element name="{$grouping_tag}" >
            <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute>
            <xsl:for-each select="current-group()/*">                    
                <xsl:copy>
                    <xsl:apply-templates select="@*"/>
                    <xsl:apply-templates/>
                </xsl:copy>
            </xsl:for-each> 
       </xsl:element>           
     </xsl:for-each-group>

</xsl:template>

This solution does indeed group adjacent aside with the same class, but in the output I lost everything that is not contained in them (for example, p, img). And I need to mantain everything else, and in the same position.

Can someone help me?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

山人契 2025-02-20 10:33:45

我将使用select =“*” group-adjacent =“。 1]要检查组的旁边元素并包裹它们,否则将组通过申请表推动。

I would use select="*" group-adjacent=". instance of element(aside), @class" composite="yes" and then you can test current-group()[1] to check the group has aside elements and wrap them, otherwise push the group through apply-templates.

一人独醉 2025-02-20 10:33:45

也许是这样?

<xsl:template match="body">
     <xsl:for-each-group select="aside" group-adjacent="@class">
        <xsl:choose>
           <xsl:when test="@class">
               <xsl:element name="tag{@class}">
                  <xsl:copy-of select="current-group()"/>
               </xsl:element>
           </xsl:when>
           <xsl:otherwise>
               <xsl:copy-of select="current-group()"/>
           </xsl:otherwise>
        </xsl:choose>     
     </xsl:for-each-group>

</xsl:template>

Something like this, perhaps?

<xsl:template match="body">
     <xsl:for-each-group select="aside" group-adjacent="@class">
        <xsl:choose>
           <xsl:when test="@class">
               <xsl:element name="tag{@class}">
                  <xsl:copy-of select="current-group()"/>
               </xsl:element>
           </xsl:when>
           <xsl:otherwise>
               <xsl:copy-of select="current-group()"/>
           </xsl:otherwise>
        </xsl:choose>     
     </xsl:for-each-group>

</xsl:template>
骄兵必败 2025-02-20 10:33:45

我想您可以做类似:

<xsl:template match="body">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="boolean(self::aside)">
            <xsl:choose>
                <xsl:when test="current-grouping-key()">
                    <xsl:for-each-group select="current-group()" group-adjacent="@class">
                        <xsl:element name="tag{if (@class=(1,2)) then @class else 'X'}" >
                            <xsl:attribute name="class" select="@class"/>
                            <xsl:copy-of select="current-group()/node()"/>                  
                        </xsl:element>  
                    </xsl:for-each-group>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="current-group()"/>                 
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

ps的事情:如果一边,那么您可以将其缩短为:

<xsl:template match="body">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="string(@class)">
            <xsl:choose>
                <xsl:when test="@class">
                    <xsl:element name="tag{if (@class=(1,2)) then @class else 'X'}" >
                        <xsl:attribute name="class" select="@class"/>
                        <xsl:copy-of select="current-group()/node()"/>                    
                    </xsl:element>  
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="current-group()"/>                    
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

I guess you could do something like:

<xsl:template match="body">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="boolean(self::aside)">
            <xsl:choose>
                <xsl:when test="current-grouping-key()">
                    <xsl:for-each-group select="current-group()" group-adjacent="@class">
                        <xsl:element name="tag{if (@class=(1,2)) then @class else 'X'}" >
                            <xsl:attribute name="class" select="@class"/>
                            <xsl:copy-of select="current-group()/node()"/>                  
                        </xsl:element>  
                    </xsl:for-each-group>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="current-group()"/>                 
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

P.S. If aside elements are the only child elements of body that have a (non-empty) class attribute, then you could shorten this to:

<xsl:template match="body">
    <xsl:copy>
        <xsl:for-each-group select="*" group-adjacent="string(@class)">
            <xsl:choose>
                <xsl:when test="@class">
                    <xsl:element name="tag{if (@class=(1,2)) then @class else 'X'}" >
                        <xsl:attribute name="class" select="@class"/>
                        <xsl:copy-of select="current-group()/node()"/>                    
                    </xsl:element>  
                </xsl:when>
                <xsl:otherwise>
                    <xsl:copy-of select="current-group()"/>                    
                </xsl:otherwise>
            </xsl:choose>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文