title: Grouping values with same attributes using xslt-1.0
body: <p>Given this input XML:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
  &lt;agrisResources xmlns:ags="http://purl.org/agmes/1.1/" xmlns:dc="http://purl.org/dc/elements/1.1/"&gt;
      &lt;agrisResource bibliographicLevel="AM" ags:ARN="^aSF17^b00003"&gt;
          &lt;dc:subject xml:lang="en"&gt;Penaeidae&lt;/dc:subject&gt;
          &lt;dc:subject xml:lang="en"&gt;Vibrio harveyi&lt;/dc:subject&gt;
          &lt;dc:subject xml:lang="en"&gt;Vibrio parahaemolyticus&lt;/dc:subject&gt;
          &lt;dc:subject&gt;
              &lt;ags:subjectClassification scheme="ags:ASC"&gt;ASFA-1&lt;/ags:subjectClassification&gt;
              &lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;Bacterial diseases&lt;/ags:subjectThesaurus&gt;
              &lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;Fish diseases&lt;/ags:subjectThesaurus&gt;
              &lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;Genes&lt;/ags:subjectThesaurus&gt;
          &lt;/dc:subject&gt;
      &lt;/agrisResource&gt;
  &lt;/agrisResources&gt;
  </code></pre>
  
  <p>I would like to group items with the same attributes, so the output would be like this:</p>
  
  <pre><code>&lt;dc:subject xml:lang="en"&gt;Penaeidae||Vibrio harveyi||Vibrio parahaemolyticus&lt;/dc:subject&gt;
  &lt;dc:subject&gt;
      &lt;ags:subjectClassification scheme="ags:ASC"&gt;ASFA-1&lt;/ags:subjectClassification&gt;
      &lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;Bacterial diseases||Fish diseases||Genes&lt;/ags:subjectThesaurus&gt;
  &lt;/dc:subject&gt;
  </code></pre>
  
  <p>Basically, my rule for the grouping is to combine the values of the nodes if that node have multiple values, eg <code>dc:subject</code>, and <code>ags:subjectThesaurus</code>. I specify in my title to <strong>group values with same attributes</strong> because I'm not really sure if it is possible to just group them by their tags without specifying their attributes to differentiate them.</p>
  
  <p>In other words, differentiate</p>
  
  <pre><code>&lt;dc:subject&gt;Penaeidae&lt;/dc:subject&gt;
  </code></pre>
  
  <p>from</p>
  
  <pre><code>&lt;dc:subject&gt;
      &lt;ags:subjectThesaurus&gt;Bacterial diseases&lt;/ags:subjectThesaurus&gt;
  &lt;/dc:subject&gt;
  </code></pre>
  
  <p><strong>UPDATE</strong></p>
  
  <p><strong>INPUT XML</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
  &lt;agrisResources xmlns:ags="http://purl.org/agmes/1.1/" xmlns:dc="http://purl.org/dc/elements/1.1/"&gt;
      &lt;agrisResource bibliographicLevel="AM" ags:ARN="^aSF17^b00003"&gt;
          &lt;dc:creator&gt;
              &lt;ags:creatorPersonal&gt;Doe, John&lt;/ags:creatorPersonal&gt;
              &lt;ags:creatorPersonal&gt;Smith, Jason T.&lt;/ags:creatorPersonal&gt;
              &lt;ags:creatorPersonal&gt;Doe, Jane E.&lt;/ags:creatorPersonal&gt;
          &lt;/dc:creator&gt;
          &lt;dc:subject xml:lang="en"&gt;Penaeidae&lt;/dc:subject&gt;
          &lt;dc:subject xml:lang="en"&gt;Vibrio harveyi&lt;/dc:subject&gt;
          &lt;dc:subject xml:lang="en"&gt;Vibrio parahaemolyticus&lt;/dc:subject&gt;
          &lt;dc:subject&gt;
              &lt;ags:subjectClassification scheme="ags:ASC"&gt;ASFA-1&lt;/ags:subjectClassification&gt;
              &lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;Bacterial diseases&lt;/ags:subjectThesaurus&gt;
              &lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;Fish diseases&lt;/ags:subjectThesaurus&gt;
              &lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;Genes&lt;/ags:subjectThesaurus&gt;
          &lt;/dc:subject&gt;
      &lt;/agrisResource&gt;
  &lt;/agrisResources&gt;
  </code></pre>
  
  <p><strong>Desired Output</strong></p>
  
  <p>Rules on grouping: Combine the values using double pipe <code>||</code> as separator for repeating elements, eg <code>&lt;ags:creatorPersonal&gt;</code>, <code>&lt;dc:subject xml:lang="en"&gt;</code> and <code>&lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;</code>. Leave other elements as is that does not meet that rule.</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;
  &lt;agrisResources xmlns:ags="http://purl.org/agmes/1.1/" xmlns:dc="http://purl.org/dc/elements/1.1/"&gt;
      &lt;agrisResource bibliographicLevel="AM" ags:ARN="^aSF17^b00003"&gt;
          &lt;dc:creator&gt;
              &lt;ags:creatorPersonal&gt;Doe, John||Smith, Jason T.||Doe, Jane E.&lt;/ags:creatorPersonal&gt;
          &lt;/dc:creator&gt;
          &lt;dc:subject xml:lang="en"&gt;Penaeidae||Vibrio harveyi||Vibrio parahaemolyticus&lt;/dc:subject&gt;
          &lt;dc:subject&gt;
              &lt;ags:subjectClassification scheme="ags:ASC"&gt;ASFA-1&lt;/ags:subjectClassification&gt;
              &lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;Bacterial diseases||Fish diseases||Genes&lt;/ags:subjectThesaurus&gt;
          &lt;/dc:subject&gt;
      &lt;/agrisResource&gt;
  &lt;/agrisResources&gt;
  </code></pre>
  
  <p>Below is my code based from this <a href="https://stackoverflow.com/a/16023219/1919069%22answer%22">answer</a>:</p>
  
  <pre><code>&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dc="http://purl.org/dc/terms/"
              xmlns:ags="http://purl.org/agmes/1.1/"
              xmlns:agls="http://www.naa.gov.au/recordkeeping/gov_online/agls/1.2"
              xmlns:dcterms="http://purl.org/dc/terms/"&gt;
      &lt;xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/&gt;
      &lt;xsl:strip-space elements="*"/&gt;
  
      &lt;xsl:template match="@* | node()"&gt;
          &lt;xsl:copy&gt;
              &lt;xsl:apply-templates select="@* | node()"/&gt;
          &lt;/xsl:copy&gt;
      &lt;/xsl:template&gt;
  
      &lt;xsl:template match="ags:subjectThesaurus|dc:subject"&gt;
          &lt;xsl:copy&gt;
              &lt;xsl:apply-templates select="@* | text()"/&gt;
                  &lt;xsl:call-template name="NextSibling"/&gt;
          &lt;/xsl:copy&gt;
      &lt;/xsl:template&gt;
      &lt;xsl:template match="ags:subjectThesaurus[@scheme = preceding-sibling::*[1][self::ags:subjectThesaurus]/@scheme]|dc:subject[@xml:lang = preceding-sibling::*[1][self::dc:subject]/@xml:lang]"/&gt;
  
      &lt;xsl:template match="ags:subjectThesaurus|dc:subject" mode="includeSib"&gt;
          &lt;xsl:value-of select="concat('||', .)"/&gt;
              &lt;xsl:call-template name="NextSibling"/&gt;
          &lt;/xsl:template&gt;
  
      &lt;xsl:template name="NextSibling"&gt;
          &lt;xsl:apply-templates select="following-sibling::*[1][self::ags:subjectThesaurus and @scheme = current()/@scheme]|following-sibling::*[1][self::dc:subject and @xml:lang = current()/@xml:lang]" mode="includeSib"/&gt;
      &lt;/xsl:template&gt;
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p>My only problem is that it is only transforming the <code>ags:subjectThesaurus</code> but not the <code>dc:subject</code> node. My output looks like this:</p>
  
  <pre><code>&lt;dc:subject xml:lang="en"&gt;Penaeidae&lt;/dc:subject&gt;
  &lt;dc:subject xml:lang="en"&gt;Vibrio harveyi&lt;/dc:subject&gt;
  &lt;dc:subject xml:lang="en"&gt;Vibrio parahaemolyticus&lt;/dc:subject&gt;
  &lt;dc:subject&gt;
      &lt;ags:subjectThesaurus xml:lang="en" scheme="ags:ASFAT"&gt;Bacterial diseases||Fish diseases||Genes&lt;/ags:subjectThesaurus&gt;
  &lt;/dc:subject&gt;
  </code></pre>
  
  <p>How can I modify my code such that it will also group the <code>dc:subject</code> node with the same <code>xml:lang</code> attribute?</p>
  
  <p><strong>EDIT</strong></p>
  
  <p>Based on the suggestion of <a href="https://stackoverflow.com/users/3016153/michael-hor257k">michael.hor257k</a> and from this <a href="https://stackoverflow.com/a/16034747/1919069">answer</a> to use the Muenchian method, below is what I tried:</p>
  
  <pre><code>&lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dc="http://purl.org/dc/terms/"
              xmlns:ags="http://purl.org/agmes/1.1/"
              xmlns:agls="http://www.naa.gov.au/recordkeeping/gov_online/agls/1.2"
              xmlns:dcterms="http://purl.org/dc/terms/"&gt;
      &lt;xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/&gt;
      &lt;xsl:strip-space elements="*"/&gt;
      &lt;xsl:key name="kNodeSubject" match="dc:subject[@xml:lang]" use="@xml:lang"/&gt;
      &lt;xsl:key name="subjectThesaurus" match="dc:subject/ags:subjectThesaurus" use="@scheme"/&gt;
      &lt;xsl:template match="node() | @*"&gt;
          &lt;xsl:copy&gt;
              &lt;xsl:apply-templates select="node() | @*"/&gt;
          &lt;/xsl:copy&gt;
      &lt;/xsl:template&gt;
      &lt;xsl:template match="dc:subject[generate-id() = generate-id(key('kNodeSubject', @xml:lang)[1])]"&gt;
          &lt;xsl:copy&gt;
              &lt;xsl:apply-templates select="@*"/&gt;
              &lt;xsl:apply-templates select="key('kNodeSubject', @xml:lang)" mode="concat"/&gt;
          &lt;/xsl:copy&gt;
      &lt;/xsl:template&gt;
  
      &lt;xsl:template match="dc:subject/ags:subjectThesaurus[generate-id() = generate-id(key('subjectThesaurus', @scheme)[1])]"&gt;
          &lt;xsl:copy&gt;
              &lt;xsl:apply-templates select="@*"/&gt;
              &lt;xsl:apply-templates select="key('subjectThesaurus', @scheme)" mode="concat"/&gt;
          &lt;/xsl:copy&gt;
      &lt;/xsl:template&gt;
  
      &lt;xsl:template match="dc:subject|subjectThesaurus" mode="concat"&gt;
          &lt;xsl:value-of select="."/&gt;
              &lt;xsl:if test="position() != last()"&gt;
                  &lt;xsl:text&gt;||&lt;/xsl:text&gt;
              &lt;/xsl:if&gt;
      &lt;/xsl:template&gt;
  
      &lt;xsl:template match="dc:subject"/&gt;
      &lt;xsl:template match="ags:subjectThesaurus"/&gt;
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p>When I applied the code above, the nodes <code>ags:subjectThesaurus</code> are gone and the values of <code>&lt;dc:subject xml:lang="en"&gt;</code> are not grouped either. I don't know if I have the match right, I used the <code>match="dc:subject[@xml:lang]"</code> for the <code>&lt;xsl:key name="kNodeSubject"</code> because the node <code>ags:subjectThesaurus</code> is the child of <code>&lt;dc:subject&gt;</code>.</p>
  
  <p>Thanks in advance.</p>