Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
233 views
in Technique[技术] by (71.8m points)

xslt - Group Similar nodes in XML using XLST

I found a similar question to mine, but couldn't figure out a way for my issue.

I have an XML as follows

<name>
    <text class="002. AB vs BC">  Sample</text>
    <text class="003. DC vs BC">  Sample</text>
    <text class="004. CD vs BC">  Sample</text>
    <text class="005. AB vs BC">  Sample</text>
    <text class="006. AB vs BC">  Sample</text>
    <text class="007. EF vs BC">  Sample</text>
    <text class="008. CD vs BC">  Sample</text>
    <text class="009. DC vs BC">  Sample</text>
    <text class="010. AB vs BC">  Sample</text>
    <text class="011. EF vs BC">  Sample</text>
    <text class="012. AB vs BC">  Sample</text>

</name>

And I need to group all the nodes with similar first word in class attribute as follows

<name>
    <group name="AB">
        <text class="002. AB vs BC">  Sample</text>
        <text class="005. AB vs BC">  Sample</text>
        <text class="006. AB vs BC">  Sample</text>
        <text class="010. AB vs BC">  Sample</text>
        <text class="012. AB vs BC">  Sample</text>
    </group>
    <group name="EF">
        <text class="007. EF vs BC">  Sample</text>
        <text class="011. EF vs BC">  Sample</text>
    </group>
    <group name="CD">
        <text class="008. CD vs BC">  Sample</text>
        <text class="004. CD vs BC">  Sample</text>
    </group>
    <group name="DC">
        <text class="003. DC vs BC">  Sample</text>
        <text class="009. DC vs BC">  Sample</text>
    </group>
</name>

How to achieve this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is a pretty straightforward grouping problem.

If you're limited to XSLT 1.0, you need to use Muenchian Grouping.

If you're using XSLT 2.0+, you can use xsl:for-each-group.

Examples...

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="class" match="text" 
    use="substring-before(substring-after(normalize-space(@class), ' '),' ')"/>

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

  <xsl:template match="/name">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each select="text[count(.|key('class', substring-before(substring-after(normalize-space(@class), ' '),' '))[1])=1]">
        <xsl:variable name="key" select="substring-before(substring-after(normalize-space(@class), ' '),' ')"/>
        <group name="{$key}">
          <xsl:apply-templates select="key('class',$key)"/>
        </group>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Fiddle: http://xsltfiddle.liberty-development.net/94hvTyR

XSLT 3.0 (you can make this valid 2.0 if you replace the xsl:mode with the identity template from the 1.0 stylesheet)

<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="name">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select="text" 
        group-by="tokenize(normalize-space(@class),'s+')[2]">
        <group name="{current-grouping-key()}">
          <xsl:apply-templates select="current-group()"/>
        </group>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Fiddle: http://xsltfiddle.liberty-development.net/94hvTyR/1

Note: The output does not have the same order as your example, but I didn't see any logic to the ordering.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...