1
votes

I'm struggeling on a piece of code, any help would be appreciated.

To make the story short, in my XSLT(2.0) file I have 2 nested loops. The first one performs a grouping based on year value. For each of these group, the inner loop performs some operations. In this particular loop, while performing tasks in the current group, I need to know the size(the number of elements) of the previous group. Of course, I can't figure out how to achieve this.

Here is a piece of XSLT code :

<xsl:for-each-group select=" ... " group-by="year">


        <xsl:for-each select="current-group()">

            <!-- Here I want to know the number of elements of previous group -->

        </xsl:for-each>
 </xsl:for-each-group>

For the first group, of course size needs to be 0 because there are no previous group yet. For following group (second, third, ...), I need to know the number of elements of the previous one.

So for example, if we have two groups :

  • 2007 group with elements data1 data2 data3 data4
  • 2009 group with elements data5 data6

When the inner loop perform operations on '2009 group', I need to know that 2007 group has 4 elements. (data1 data2 data3 data4)


More details !

Here is how my XML file looks like. You have a root racine called 'dblp', in which you can find either 'proceedings' or 'inproceedings' tag. Each of these consist of a description of a publication with the title,year,authors/editors, ... .

<dblp>
<proceedings mdate="2007-08-28" key="conf/adma/2007">
    <editor>Reda Alhajj</editor>
    <editor>Hong Gao</editor>
    <editor>Xue Li</editor>
    <editor>Jianzhong Li</editor>
    <editor>Osmar R. Zaïane</editor>
    <title>Advanced Data Mining and Applications, Third International Conference, ADMA 2007, Harbin, China, August 6-8, 2007, Proceedings</title>
    <booktitle>ADMA</booktitle>
    <series href="db/journals/lncs.html">Lecture Notes in Computer Science</series>
    <volume>4632</volume>
    <publisher>Springer</publisher>
    <year>2009</year>
    <isbn>978-3-540-73870-1</isbn>
    <url>db/conf/adma/adma2007.html</url>
</proceedings>
<proceedings mdate="2007-08-28" key="conf/adma/2007">
    <editor>Reda Alhajj</editor>
    <editor>Hong Gao</editor>
    <editor>Xue Li</editor>
    <editor>Jianzhong Li</editor>
    <editor>Osmar R. Zaïane</editor>
    <title>Advanced Data Mining and Applications, Third International Conference, ADMA 2007, Harbin, China, August 6-8, 2007, Proceedings</title>
    <booktitle>ADMA</booktitle>
    <series href="db/journals/lncs.html">Lecture Notes in Computer Science</series>
    <volume>4632</volume>
    <publisher>Springer</publisher>
    <year>1999</year>
    <isbn>978-3-540-73870-1</isbn>
    <url>db/conf/adma/adma2007.html</url>
</proceedings>
<inproceedings mdate="2007-08-28" key="conf/adma/YangLH07">
    <author>Hui Yang</author>
    <author>Reda Alhajj</author>
    <author>Hongyan Liu</author>
    <author>Jun He</author>
    <title>DELAY : A Lazy Approach for Mining Frequent Patterns over High Speed Data Streams.</title>
    <pages>2-14</pages>
    <year>2009</year>
    <crossref>conf/adma/2007</crossref>
    <booktitle>ADMA</booktitle>
    <ee>http://dx.doi.org/10.1007/978-3-540-73871-8_2</ee>
    <url>db/conf/adma/adma2007.html#YangLH07</url>
</inproceedings>
<inproceedings mdate="2007-11-29" key="conf/adma/GuoKG07">
    <author>Yi Guo</author>
    <author>Reda Alhajj</author>
    <author>Paul Wing Hing Kwan</author>
    <author>Junbin Gao</author>
    <title>Learning Optimal Kernel from Distance Metric in Twin Kernel Embedding for Dimensionality Reduction and Visualization of Fingerprints.</title>
    <pages>227-238</pages>
    <year>2007</year>
    <crossref>conf/adma/2007</crossref>
    <booktitle>ADMA</booktitle>
    <ee>http://dx.doi.org/10.1007/978-3-540-73871-8_22</ee>
    <url>db/conf/adma/adma2007.html#GuoKG07</url>
</inproceedings>

Here is my previous XSLT piece of code :

<xsl:for-each-group select="/dblp/*/editor[text() = $currentEditor] | /dblp/*/author[text() = $currentEditor]" group-by="../year">
     <xsl:value-of select="current-grouping-key()"/>
     <xsl:for-each select="current-group()">
         <xsl:variable name="titre" select="(../title)"/>
         <xsl:variable name="linkEE" select="(../ee)"/>
     </xsl:for-each>
</xsl:for-each-group>

The "xsl:for-each-group" performs a grouping based on the year value of the publications (proceedings,inproceedings). As you can see, I select a specific editor or author. For exemple, $currentEditor can be 'Reda Alhajj'. For 'Reda Alhajj' it will create 3 groups : 2009 group (with 1 proceedings + 1 inproceedings), 2007 group (with 1 inproceeding) and 1999 group (with 1 proceeding) (as you can see in the XML file) Then, the inner loop, will loop over the element of each group to retrieve more informations (title, link, ..).

My question : how can I achieve the same behaviour with the new xslt code ?

<xsl:for-each select="$groups/group">
      how to get current-grouping-key ??
     <xsl:for-each select="*">  title ?? link ??</xsl:for-each>
</xsl:for-each>

BIG thanks !


I reworked the code provided by Martin Hoonen, and here is my current XSLT piece of code.

<xsl:variable name="groups">
<xsl:for-each-group select="/dblp/*/editor[text() = $currentEditor] | /dblp/*/author[text() = $currentEditor]" group-by="../year">
    <group  year="{../year}">
            <xsl:for-each select="current-group()">
                <elem  titre="{../title}" linkEE="{../ee}" editeurs="{../author | ../editor}">
                </elem>
            </xsl:for-each>
    </group>
</xsl:for-each-group>
</xsl:variable>


<xsl:for-each select="$groups/group">
     <xsl:value-of select="@year"/>

     <xsl:for-each select="elem">
          <xsl:variable name="person" select="@editeurs"/>
          <xsl:for-each select="$person">
               <!-- NOT WORKING TO LOOP SEPARATELY OVER EACH AUTHOR/EDITOR : gives me all author/editors of elem at the first iteration of loop -->
               <xsl:value-of select="."/>
          </xsl:for-each>
     </xsl:for-each>
 </xsl:for-each>

In the variable "groups", I have a tag "group" which corresponds to a general group (classified by year). In this "group" tag, I have added a "elem" tag which corresponds to publications. In deed, a group can consists of several publications (i.e in 2009, there a for example two publications so I have 2 "elem" in this "group", and for each of these elem I save title, ..).

My problem is for the authors/editors. As you can see from the XML file, I can have multiple distinct author or editor in a publication (for example in the first proceedings of my XML file, I have 5 editors). I would like later to be able to loop over each of them separately. for the moment, I save them as an attribute of "elem" as you can see, but then they are saved as a string and I cannot loop over each of them separately. Does anybody have an idea to achieve that ?

For the moment the loop over $person gives me this result : Hui Yang Reda Alhajj Hongyan Liu Jun He

Instead of (separature values on wich I can perfom specific treatment) :

  • Hui Yang
  • Reda Alhajj
  • Hongyan Liu
  • Jun He

Any help appreciated ! :)

1
Would you explain what you need the previous count for?Tomalak
Your clarification would be a lot clearer if it showed the expected output.michael.hor257k

1 Answers

3
votes

You will need to store your groups into a variable structured as needed e.g.

<xsl:variable name="groups">
  <xsl:for-each-group select=" ... " group-by="year">
    <group>
      <xsl:copy-of select="current-group()"/>
    </group>
  </xsl:for-each-group>
</xsl:variable>

Now here you can use

<xsl:for-each select="$groups/group">
  <!-- to compute the size of the previous group -->
  <xsl:variable name="psize" select="count(preceding-sibling::group[1]/*)"/>
  <!-- to iterate over the elements in each group -->
  <xsl:for-each select="*">...</xsl:for-each>
</xsl:for-each>

Based on your edit it seems you group editor and author elements by the year of the parent element and then you want to access other elements like title or ee of the parent element. If you know you need these two values then you could change the grouping code to store them with e.g.

<xsl:variable name="groups">
  <xsl:for-each-group select="/dblp/*/editor[. = $currentEditor] | /dblp/*/author[. = $currentEditor]" group-by="../year">
    <group title="{../title}" ee="{../ee}">
      <xsl:copy-of select="current-group()"/>
    </group>
  </xsl:for-each-group>
</xsl:variable>

which would then allow you to access the values later as attributes with e.g.

<xsl:for-each select="$groups/group">
  <!-- to compute the size of the previous group -->
  <xsl:variable name="psize" select="count(preceding-sibling::group[1]/*)"/>
  <!-- the common, stored values -->
  <xsl:variable name="title" select="@title"/>
  <xsl:variable name="ee" select="@ee"/>
  <!-- to iterate over the elements in each group -->
  <xsl:for-each select="*">...</xsl:for-each>
</xsl:for-each>