Объединение элементов с помощью XSLT

Я пытался объединить элементы xml из books.xml, которые имеют одинаковое значение атрибута

Это исходный XML:

 <?xml version="1.0" encoding="UTF-8"?>
  <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="bk101">
      <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="bk102">
      <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>
</catalog>

Это мой желаемый результат:

<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>
      <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>
      <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>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>
      <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>
</catalog>

И ниже xslt, который я пробовал, который не дает желаемых результатов.

<?xml version="1.0" encoding="UTF-8" ?>

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

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

    <xsl:template match="book">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
      <xsl:variable name="info" select="." />
      <xsl:for-each select="$info">
        <xsl:if test="@id=$info/@id">
          <xsl:copy-of select="." />
        </xsl:if>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

person saikiran Mallam    schedule 02.06.2017    source источник
comment
Учитывая, что вы использовали теги xslt-2.0 и xslt-grouping, вы сможете начать с примера из w3.org/TR/xslt20/#grouping-examples, а затем используйте xsl:for-each-group select="book" group-by="@id" для решения.   -  person Martin Honnen    schedule 02.06.2017


Ответы (1)


Для XSLT 1.0 рассмотрите метод Мюнхи, в котором вы назначаете ключ каждому отдельному book/@id, а затем перебрать каждый ключ и соответствующие дочерние узлы:

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

    <xsl:key name="bookid" match="book" use="@id"/>

    <xsl:template match="/catalog">  
        <xsl:copy> 
            <xsl:for-each select="book[count(. | key('bookid', @id)[1]) = 1]">
                <xsl:copy> 
                    <xsl:copy-of select="@*" />                     
                    <xsl:for-each select="key('bookid',@id)">  
                        <xsl:copy-of select="*" />      
                    </xsl:for-each>              
                </xsl:copy>       
            </xsl:for-each>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

В качестве альтернативы, с помощью предложенной @ MartinHonnen помощи, таблицы стилей без xsl:for-each:

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

    <xsl:key name="bookid" match="book" use="@id"/>

    <xsl:template match="/catalog">  
        <xsl:copy> 
            <xsl:apply-templates select="book[generate-id() = generate-id(key('bookid', @id)[1])]"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="book"> 
        <xsl:copy>          
            <xsl:copy-of select="@*| key('bookid',@id)/*" /> 
        </xsl:copy>       
    </xsl:template>

</xsl:stylesheet>

Выход

<?xml version="1.0"?>
<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>
    <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>
    <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>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>
    <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>
</catalog>

person Parfait    schedule 02.06.2017
comment
<xsl:for-each select="key('bookid',@id)"><xsl:copy-of select="*" /></xsl:for-each> можно было бы сократить до <xsl:copy-of select="key('bookid',@id)/*" /> . - person Martin Honnen; 02.06.2017
comment
@MartinHonnen ... Отлично! Искал способ запустить скрипт без xsl:for-each. - person Parfait; 02.06.2017