xslt группировка и удаление дубликатов

<Items>
    <array>
        <item name="A">
            <name>A</name>
            <indate>20141112</indate>
            <inno>2</inno>
            <status>1</status>
            <level>12</level>
            <size>.1</size>
            <text>item a text </text>
        </item>
        <item name="B">
            <name>B</name>
            <indate>20141012</indate>
            <inno>5</inno>
            <status>1</status>
            <level>13</level>
            <size>.5</size>
            <text>item b text </text>
        </item>
        <item name="C">
            <name>C</name>
            <indate>20140912</indate>
            <inno>6</inno>
            <status>1</status>
            <level>12</level>
            <size>.2</size>
            <text>item c text </text>
        </item>
        <item name="A">
            <name>A</name>
            <ondate>20140612</ondate>
            <onno>9</onno>
        </item>
        <item name="B">
            <name>B</name>
            <ondate>20140212</ondate>
            <inno>7</inno>
        </item>
        <item name="D">
            <name>D</name>
            <indate>20140712</indate>
            <inno>9</inno>
        </item>
        <item name="A">
            <name>A</name>
            <status>1</status>
            <level>12</level>
            <size>.1</size>
            <text>item a text </text>
        </item>
        <item name="B">
            <name>B</name>
            <status>1</status>
            <level>13</level>
            <size>.5</size>
            <text>item b text </text>
        </item>
        <item name="D">
            <name>D</name>
            <status>1</status>
            <level>13</level>
            <size>.9</size>
            <text>item d text </text>
        </item>
    </array>
</Items>

У меня есть этот xml, и мне нужно сгруппировать его для следующего вывода и добавить элементы inno и onno, чтобы получить sumno. И проверьте indate и ondate, чтобы получить большую дату. И давайте пустые элементы всякий раз, когда inno/onno/indate/ondate отсутствуют. И удалите дубликаты. как написать это мюнхенским методом

вывод:

<Items>
    <array>
        <item name="A">
            <name>A</name>
            <indate>20141112</indate>
            <inno>2</inno>
            <ondate>20140612</ondate>
            <onno>9</onno>
            <latedate>20141112</latedate>
            <sumno>11</sumno>
            <status>1</status>
            <level>12</level>
            <size>.1</size>
            <text>item a text </text>
        </item>
        <item name="B">
            <name>B</name>
            <indate>20141012</indate>
            <inno>5</inno>
            <ondate>20140212</ondate>
            <onno>7</onno>
            <latedate>20141012</latedate>
            <sumno>12</sumno>
            <status>1</status>
            <level>13</level>
            <size>.5</size>
            <text>item b text </text>
        </item>
        <item name="C">
            <name>C</name>
            <indate>20140912</indate>
            <inno>6</inno>
            <ondate/>
            <onno/>
            <latedate>20140912</latedate>
            <sumno>6</sumno>
            <status>1</status>
            <level>12</level>
            <size>.2</size>
            <text>item c text </text>
        </item>
        <item name="D">
            <name>D</name>
            <indate/>
            <inno/>
            <ondate>20140712</ondate>
            <onno>7</onno>
            <latedate>20140712</latedate>
            <sumno>7</sumno>
            <status>1</status>
            <level>13</level>
            <size>.9</size>
            <text>item d text </text>
        </item>
    </array>
</Items>

Я использовал этот xsl для группировки, но не мог добавлять и удалять дубликаты.

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

            <xsl:key name="items-by-id" match="item[@name]" use="name"/>
            <xsl:template match="@* | node()">
                        <xsl:copy>
                                    <xsl:apply-templates select="@* | node()"/>
                        </xsl:copy>
            </xsl:template>
            <xsl:template match="array">
                        <xsl:copy>
                                    <xsl:apply-templates select="item[@name][generate-id() = generate-id(key('items-by-id', name)[1])]" mode="group"/>
                        </xsl:copy>
            </xsl:template>
            <xsl:template match="item[@name]" mode="group">
                        <xsl:copy>
                                    <xsl:copy-of select="name"/>
                                    <xsl:apply-templates select="key('items-by-id', name)"/>
            </xsl:copy>
            </xsl:template>
            <xsl:template match="item[@name]">
                        <xsl:apply-templates select="node()[not(self::name)]"/>
            </xsl:template>
</xsl:stylesheet>

person mnvbrtn    schedule 21.05.2015    source источник


Ответы (1)


Я думаю, что ваш код правильно группирует элементы item по их дочерним элементам name. Вы также, кажется, хотите удалить повторяющиеся дочерние элементы, я не уверен, хотите ли вы сделать это только по имени элемента или по имени элемента и содержимому элемента. Если вы хотите сделать это по имени элемента, вы можете определить второй ключ <xsl:key name="duplicated-elements" match="item/*" use="concat(../name, '|', local-name())"/>.

Что касается добавления пустых элементов, вам нужно будет проверить, существуют ли они.

Вот таблица стилей с такими проверками и вторым ключом:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="items-by-id" match="item[@name]" use="name"/>
  <xsl:key name="duplicated-elements" match="item/*" use="concat(../name, '|', local-name())"/>

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

  <xsl:template match="array">
    <xsl:copy>
      <xsl:apply-templates select="item[@name][generate-id() = generate-id(key('items-by-id', name)[1])]" mode="group"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="item[@name]" mode="group">
    <xsl:copy>
      <xsl:variable name="current-group" select="key('items-by-id', name)"/>
      <xsl:copy-of select="name"/>

      <xsl:choose>
        <xsl:when test="$current-group/indate">
          <xsl:apply-templates select="$current-group/indate"/>
        </xsl:when>
        <xsl:otherwise>
          <indate/>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:choose>
        <xsl:when test="$current-group/inno">
          <xsl:apply-templates select="$current-group/inno"/>
        </xsl:when>
        <xsl:otherwise>
          <inno/>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:choose>
        <xsl:when test="$current-group/ondate">
          <xsl:apply-templates select="$current-group/ondate"/>
        </xsl:when>
        <xsl:otherwise>
          <ondate/>
        </xsl:otherwise>
      </xsl:choose>

      <xsl:choose>
        <xsl:when test="$current-group/onno">
          <xsl:apply-templates select="$current-group/onno"/>
        </xsl:when>
        <xsl:otherwise>
          <onno/>
        </xsl:otherwise>
      </xsl:choose>

      <latedate>
        <xsl:choose>
          <xsl:when test="$current-group/indate > $current-group/ondate">
            <xsl:value-of select="$current-group/indate"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$current-group/ondate"/>
          </xsl:otherwise>
        </xsl:choose>
      </latedate>

      <sumno>
        <xsl:value-of select="sum($current-group/inno | $current-group/onno)"/>
      </sumno>

      <xsl:apply-templates select="key('items-by-id', name)/*[not(self::name | self::indate | self::inno | self::ondate | self::onno)][generate-id() = generate-id(key('duplicated-elements', concat(../name, '|', local-name()))[1])]"/>
  </xsl:copy>
</xsl:template>


</xsl:stylesheet>

Остались некоторые проблемы, такие как проверка несуществующих дат, но я надеюсь, что вы сможете с этим разобраться.

person Martin Honnen    schedule 22.05.2015