2013-06-24 3 views
3

У меня есть входной файл, как этотЗастрял группировки в XSLT 2.0

<items> 
    <item> 
     <id>5</id> 
     <name>Harry</name> 
     <age>18</age> 
     <color>blue</color> 
    </item> 
    <item> 
     <id>5</id> 
     <name>Harry</name> 
     <age>18</age> 
     <fav_food>pizza</fav_food> 
    </item> 
    <item> 
     <id>5</id> 
     <name>Harry</name> 
     <age>18</age> 
     <is_single>true</is_single> 
    </item> 
</items> 

я хотел бы группа до элементов, так что файл выглядит следующим образом

<items> 
<item> 
    <id>5</id> 
    <name>Harry</name> 
    <age>18</age> 
    <color>blue</color> 
    <fav_food>pizza</fav_food> 
    <is_single>true</is_single> 
</item> 
</items> 

EDIT - Сделал Преобразование XSLT по этой ссылке (XSLT Consolidating data when ID is the same), но это ничего не печатает.

Вот мой преобразование (с помощью XSLT 2.0) -

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

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

<xsl:template match="item"> 
    <xsl:apply-templates select="@*" /> 
    <xsl:for-each-group select="item" group-by="id"> 
    <item> 
     <id><xsl:value-of select="current-grouping-key()"/></id> 
     <xsl:apply-templates select="current-group()" /> 
    </item> 
    </xsl:for-each-group> 
</xsl:template> 

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

<xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:element> 
</xsl:template> 

</xsl:stylesheet> 
+0

При использовании XSLT 2.0, вы можете использовать 'для-каждого-group' - проверить ответ на [этот вопрос] (http://stackoverflow.com/q/11247326/1395993), что является аналогичной проблемой. –

+0

Группировка настолько отличается в XSLT 1.0 и 2.0, что вам действительно нужно сказать, что вы используете. –

+0

Извините, что я забыл указать это раньше, я использую XSLT 2.0, и я обновил свой вопрос с помощью преобразования XSLT, которое у меня есть сейчас. – Narabhut

ответ

1

Основная проблема, которую вы имеете, у вас есть шаблон, совпадающий с элемента элемент:

<xsl:template match="item"> 

Но в этом, вы имеют xsl: для каждой группы, что также ищет шт. элементы

<xsl:for-each-group select="item" group-by="id"> 

Что это означает, что вы ищете пункта элементов, которые являются потомками других элементов элементов, из которых их нет в XML. Я думаю, что нужно объединить первые два шаблона в один здесь:

<xsl:template match="items"> 
    <xsl:for-each-group select="item" group-by="id"> 
     <item> 
      .... 

Единственное, что не ясно, какие элементы в пределах пункта элементов будут повторяться. Всегда ли это имя, имя и возраст? Вероятно, лучше всего быть гибким здесь, и предположить, что только id будет общим элементом. Я также предполагаю, что если повторяются два элемента (например, имя), он всегда будет иметь такое же значение.

Таким образом, чтобы получить все другие различные элементы без идентификаторов, вы могли бы еще некоторые группировки по имени элемента

<xsl:for-each-group select="current-group()/*[not(self::id)]" group-by="local-name()"> 

Затем, в течение этого цикла вы можете просто вывести элемент.

Попробуйте XSLT

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

<xsl:template match="items"> 
    <xsl:for-each-group select="item" group-by="id"> 
    <item> 
     <id><xsl:value-of select="current-grouping-key()"/></id> 
     <xsl:for-each-group select="current-group()/*[not(self::id)]" group-by="local-name()"> 
     <xsl:apply-templates select="self::*" /> 
     </xsl:for-each-group> 
    </item> 
    </xsl:for-each-group> 
</xsl:template> 

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

<xsl:template match="*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:element> 
</xsl:template> 

</xsl:stylesheet> 

Применительно к вашему XML, следующий выход

<item> 
    <id>5</id> 
    <name>Harry</name> 
    <age>18</age> 
    <color>blue</color> 
    <fav_food>pizza</fav_food> 
    <is_single>true</is_single> 
</item> 
+0

Это сработало отлично. Большое спасибо, и я ценю подробное объяснение! – Narabhut

Смежные вопросы