XSLT 1.0: Grouping and Duplicate Removal

I have a problem with xml grouping for which I need to group AND delete the duplicate as below:

<Person>
<name>John</name>
<date>June12</date>
<workTime taskID=1>34</workTime>
<workTime taskID=1>35</workTime>
<workTime taskID=2>12</workTime>
</Person>
<Person>
<name>John</name>
<date>June13</date>
<workTime taskID=1>21</workTime>
<workTime taskID=2>11</workTime>
<workTime taskID=2>14</workTime>
</Person>

Please note that for the specific appearance of the name / taskID / date, only the first one is selected. In this example

<workTime taskID=1>35</workTime> 
<workTime taskID=2>14</workTime> 

will be left aside.

Below is the expected result:

<Person>
<name>John</name>
<taskID>1</taskID>
<workTime>
<date>June12</date>
<time>34</time>
</worTime>
<workTime>
<date>June13</date>
<time>21</time>
</worTime>
</Person>
<Person>
<name>John</name>
<taskID>2</taskID>
<workTime>
<date>June12</date>
<time>12</time>
</worTime>
<workTime>
<date>June13</date>
<time>11</time>
</worTime>
</Person>

I tried using muenchian grouping in XSLT 1.0 using the following key:

<xsl:key name="PersonTasks" match="workTime" use="concat(@taskID, ../name)"/>

but then how can I get only the first appearance

concat(@taskID, ../name, ../date)

? I think I need two levels of keys !?

+3
source share
3 answers

This conversion is :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kwrkTimeByNameTask" match="workTime"
  use="concat(../name, '+', @taskID)"/>

 <xsl:key name="kDateByName" match="date"
  use="../name"/>

 <xsl:key name="kwrkTimeByNameTaskDate" match="workTime"
  use="concat(../name, '+', @taskID, '+', ../date)"/>

 <xsl:template match="/">
   <xsl:for-each select=
    "*/*/workTime
           [generate-id()
           =
            generate-id(key('kwrkTimeByNameTask',
                             concat(../name, '+', @taskID)
                            )[1]
                        )
           ]
    ">
      <xsl:sort select="../name"/>
      <xsl:sort select="@taskID" data-type="number"/>

      <xsl:variable name="vcurTaskId" select="@taskID"/>
      <Person>
        <name><xsl:value-of select="../name"/></name>
        <taskID><xsl:value-of select="@taskID"/></taskID>

          <xsl:for-each select=
           "key('kDateByName', ../name)
                  [key('kwrkTimeByNameTaskDate',
                       concat(../name, '+', current()/@taskID, '+', .)
                      )
                  ]
           ">
             <workTime>
               <date><xsl:value-of select="."/></date>
               <time>
                <xsl:value-of select=
                 "key('kwrkTimeByNameTaskDate',
                  concat(../name, '+', $vcurTaskId, '+', .)
                 )"/>
               </time>
             </workTime>
          </xsl:for-each>
      </Person>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

XML ( , ):

<t>
    <Person>
        <name>John</name>
        <date>June12</date>
        <workTime taskID="1">34</workTime>
        <workTime taskID="1">35</workTime>
        <workTime taskID="2">12</workTime>
    </Person>
    <Person>
        <name>John</name>
        <date>June13</date>
        <workTime taskID="1">21</workTime>
        <workTime taskID="2">11</workTime>
        <workTime taskID="2">14</workTime>
    </Person>
</t>

, :

<Person>
   <name>John</name>
   <taskID>1</taskID>
   <workTime>
      <date>June12</date>
      <time>34</time>
   </workTime>
   <workTime>
      <date>June13</date>
      <time>21</time>
   </workTime>
</Person>
<Person>
   <name>John</name>
   <taskID>2</taskID>
   <workTime>
      <date>June12</date>
      <time>12</time>
   </workTime>
   <workTime>
      <date>June13</date>
      <time>11</time>
   </workTime>
</Person>

  • workTime ../name, @taskID, Muenchian .

  • ../name @taskID - .

  • workTime date , ../name workTime date workTime, ../date ../name.

  • : 'kDateByName' date ../name, 'kwrkTimeByNameTaskDate' workTime ../name, ../date @taskID.

, :

          <xsl:for-each select=
           "key('kDateByName', ../name)
                  [key('kwrkTimeByNameTaskDate',
                       concat(../name, '+', current()/@taskID, '+', .)
                      )
                  ]
           ">

:

date name, , a workTime name, date @taskID ( workTime <xsl:for-each>) , do <xsl:for-each>.

+2

, . :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kWorkTimeByName-TaskID" match="workTime" 
              use="concat(../name,'++',@taskID)"/>
    <xsl:key name="kWorkTimeByName-Date-TaskID" match="workTime" 
              use="concat(../name,'++',../date,'++',@taskID)"/>
    <xsl:template match="/">
        <xsl:variable name="vAllWorkTime" select="*/*/workTime"/>
        <result>
            <xsl:for-each select="$vAllWorkTime
                        [count(.|key('kWorkTimeByName-TaskID',
                                         concat(../name,'++',@taskID))[1])=1]">
                <xsl:sort select="../name"/>
                <xsl:sort select="@taskID" data-type="number"/>
                <Person>
                    <xsl:copy-of select="../name"/>
                    <taskID>
                        <xsl:value-of select="@taskID"/>
                    </taskID>
                    <xsl:for-each select="$vAllWorkTime
                          [count(.|key('kWorkTimeByName-Date-TaskID',
                               concat(current()/../name,'++',
                                   ../date,'++',current()/@taskID))[1])=1]">
                        <xsl:sort select="../date"/>
                        <xsl:copy>
                            <xsl:copy-of select="../date"/>
                            <time>
                                <xsl:value-of select="."/>
                            </time>
                        </xsl:copy>
                    </xsl:for-each>
                </Person>
            </xsl:for-each>
        </result>
    </xsl:template>
</xsl:stylesheet>

:

<result>
    <Person>
        <name>John</name>
        <taskID>1</taskID>
        <workTime>
            <date>June12</date>
            <time>34</time>
        </workTime>
        <workTime>
            <date>June13</date>
            <time>21</time>
        </workTime>
    </Person>
    <Person>
        <name>John</name>
        <taskID>2</taskID>
        <workTime>
            <date>June12</date>
            <time>12</time>
        </workTime>
        <workTime>
            <date>June13</date>
            <time>11</time>
        </workTime>
    </Person>
</result>
+1

Source: https://habr.com/ru/post/1760456/


All Articles