-1

I have been trying to merge all the text nodes in books.xml if their attribute values matches. And these values shoud be seperated by any delimeter(EX: , etc..)

Here is the souce XML:

<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
   <book id="bk103">
      <author>Corets, Eva</author>
      <title>Maeve Ascendant</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-11-17</publish_date>
      <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
   </book>
   <book id="bk101">
      <author>Corets, Eva</author>
      <title>Oberon's Legacy</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2001-03-10</publish_date>
      <description>In post-apocalypse England, the mysterious 
      agent known only as Oberon helps to create a new life 
      for the inhabitants of London. Sequel to Maeve 
      Ascendant.</description>
   </book>
   <book id="bk102">
      <author>Corets, Eva</author>
      <title>The Sundered Grail</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2001-09-10</publish_date>
      <description>The two daughters of Maeve, half-sisters, 
      battle one another for control of England. Sequel to 
      Oberon's Legacy.</description>
   </book>
   <book id="bk101">
      <author>Galos, Mike</author>
      <title>Visual Studio 7: A Comprehensive Guide</title>
      <genre>Computer</genre>
      <price>49.95</price>
      <publish_date>2001-04-16</publish_date>
      <description>Microsoft Visual Studio 7 is explored in depth,
      looking at how Visual Basic, Visual C++, C#, and ASP+ are 
      integrated into a comprehensive development 
      environment.</description>
   </book>
</catalog>

This is the Desired Output:

<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew  Galos, Mike  Corets, Eva</author>
      <title>XML Developer's Guide  Visual Studio 7: A Comprehensive Guide  Oberon's Legacy</title>
      <genre>Computer  Computer</genre>
      <price>44.95  49.95  5.95</price>
      <publish_date>2000-10-01  2001-04-16  2001-03-10</publish_date>
      <description>An in-depth look at creating applications 
      with XML. Microsoft Visual Studio 7 is explored in depth,
      looking at how Visual Basic, Visual C++, C#, and ASP+ are 
      integrated into a comprehensive development 
      environment.  In post-apocalypse England, the mysterious 
      agent known only as Oberon helps to create a new life 
      for the inhabitants of London. Sequel to Maeve 
      Ascendant.</description>
   <book id="bk102">
      <author>Ralls, Kim  Corets, Eva</author>
      <title>Midnight Rain  The Sundered Grail</title>
      <genre>Fantasy  Fantasy</genre>
      <price>5.95  5.95</price>
      <publish_date>2000-12-16  2001-09-10</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.  The two daughters of Maeve, half-sisters, 
      battle one another for control of England. Sequel to 
      Oberon's Legacy.</description>
   </book>
   <book id="bk103">
      <author>Corets, Eva</author>
      <title>Maeve Ascendant</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-11-17</publish_date>
      <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
   </book>
</catalog>

This is the XSLT I have been trying:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="Dbook" match="book" use="@id"/>

    <xsl:template match="/catalog">
       <xsl:copy>
        <xsl:for-each select="book[count(. | key('Dbook', @id)[1])=1]">
            <xsl:copy>
             <xsl:copy-of select="@*"/>
               <xsl:for-each select="key('Dbook',@id)">               
                   <xsl:variable name="author" select="author"/>
                   <xsl:variable name="title" select="title"/>
                   <xsl:variable name="genre" select="genre"/>
                   <xsl:variable name="price" select="price"/>
                   <xsl:variable name="publish_date" select="publish_date"/>
                   <xsl:variable name="description" select="description"/>
                   <xsl:variable name="null"/>

                   <xsl:copy-of select="concat($author,$null)"/>
                   <xsl:copy-of select="concat($title,$null)"/>
                   <xsl:copy-of select="concat($genre,$null)"/>
                   <xsl:copy-of select="concat($price,$null)"/>
                   <xsl:copy-of select="concat($publish_date,$null)"/>
                   <xsl:copy-of select="concat($description,$null)"/>

               </xsl:for-each>
            </xsl:copy>
        </xsl:for-each>
       </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
  • Please pick either XSLT 1.0 or 2.0,not both - esp. when you're asking about grouping. In XSLT 2.0, grouping is easy to accomplish using `xsl:for-each-group`. Merging the text nodes is equally trivial using `xsl:value-of` with a separator` attribute. -- Note that the output you show cannot be produced because an unescaped `&` character is not allowed in XML. – michael.hor257k Jun 03 '17 at 15:05
  • 1
    It is a problem quite similar to your previous question so perhaps you should start with accepting the answer there and then trying to adapt it to your new requirement and show us your attempt if you get stuck. By the way, if your desired output is supposed to be XML, then the delimiter needs to be escaped as `Gambardella, Matthew & Galos, Mike & Corets, Eva` – Martin Honnen Jun 03 '17 at 15:07
  • @michael.hor257k I want to achieve it with XSLT 1.0 and I am okay even if I achieve it without unescaped & character – saikiran Mallam Jun 03 '17 at 15:08

1 Answers1

1

A simple (even if tedious) solution in XSLT 1.0 would look like this:

XSLT 1.0

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

<xsl:key name="Dbook" match="book" use="@id"/>
<xsl:variable name="separator" select="' &amp; '" />

<xsl:template match="/catalog">
    <xsl:copy>
        <xsl:for-each select="book[count(. | key('Dbook', @id)[1])=1]">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:variable name="group" select="key('Dbook', @id)" />
                <author>
                    <xsl:for-each select="$group">
                        <xsl:value-of select="author"/>
                        <xsl:if test="position()!=last()">
                            <xsl:value-of select="$separator"/> 
                        </xsl:if>
                    </xsl:for-each>
                </author>
                <title>
                    <xsl:for-each select="$group">
                        <xsl:value-of select="title"/>
                        <xsl:if test="position()!=last()">
                            <xsl:value-of select="$separator"/> 
                        </xsl:if>
                    </xsl:for-each>
                </title>

                <!-- add more child elements here -->

            </xsl:copy>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Result

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <book id="bk101">
    <author>Gambardella, Matthew &amp; Corets, Eva &amp; Galos, Mike</author>
    <title>XML Developer's Guide &amp; Oberon's Legacy &amp; Visual Studio 7: A Comprehensive Guide</title>
  </book>
  <book id="bk102">
    <author>Ralls, Kim &amp; Corets, Eva</author>
    <title>Midnight Rain &amp; The Sundered Grail</title>
  </book>
  <book id="bk103">
    <author>Corets, Eva</author>
    <title>Maeve Ascendant</title>
  </book>
</catalog>

To eliminate the repetition of code for each child property of a book, you could define another key and use it as follows:

XSLT 1.0

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

<xsl:key name="Dbook" match="book" use="@id"/>
<xsl:key name="book-property" match="book/*" use="concat(../@id, '|', name())"/>

<xsl:variable name="separator" select="' &amp; '" />

<xsl:template match="/catalog">
    <xsl:copy>
        <xsl:for-each select="book[count(. | key('Dbook', @id)[1])=1]">
            <xsl:copy>
                <xsl:copy-of select="@*"/>
                <xsl:for-each select="*">
                    <xsl:copy>
                        <xsl:for-each select="key('book-property', concat(../@id, '|', name()))">
                            <xsl:value-of select="."/>
                            <xsl:if test="position()!=last()">
                                <xsl:value-of select="$separator"/> 
                            </xsl:if>
                        </xsl:for-each>
                    </xsl:copy>
                </xsl:for-each>             
            </xsl:copy>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

Result

<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <book id="bk101">
    <author>Gambardella, Matthew &amp; Corets, Eva &amp; Galos, Mike</author>
    <title>XML Developer's Guide &amp; Oberon's Legacy &amp; Visual Studio 7: A Comprehensive Guide</title>
    <genre>Computer &amp; Fantasy &amp; Computer</genre>
    <price>44.95 &amp; 5.95 &amp; 49.95</price>
    <publish_date>2000-10-01 &amp; 2001-03-10 &amp; 2001-04-16</publish_date>
    <description>An in-depth look at creating applications 
      with XML. &amp; In post-apocalypse England, the mysterious 
      agent known only as Oberon helps to create a new life 
      for the inhabitants of London. Sequel to Maeve 
      Ascendant. &amp; Microsoft Visual Studio 7 is explored in depth,
      looking at how Visual Basic, Visual C++, C#, and ASP+ are 
      integrated into a comprehensive development 
      environment.</description>
  </book>
  <book id="bk102">
    <author>Ralls, Kim &amp; Corets, Eva</author>
    <title>Midnight Rain &amp; The Sundered Grail</title>
    <genre>Fantasy &amp; Fantasy</genre>
    <price>5.95 &amp; 5.95</price>
    <publish_date>2000-12-16 &amp; 2001-09-10</publish_date>
    <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world. &amp; The two daughters of Maeve, half-sisters, 
      battle one another for control of England. Sequel to 
      Oberon's Legacy.</description>
  </book>
  <book id="bk103">
    <author>Corets, Eva</author>
    <title>Maeve Ascendant</title>
    <genre>Fantasy</genre>
    <price>5.95</price>
    <publish_date>2000-11-17</publish_date>
    <description>After the collapse of a nanotechnology 
      society in England, the young survivors lay the 
      foundation for a new society.</description>
  </book>
</catalog>
michael.hor257k
  • 113,275
  • 6
  • 33
  • 51