XSLT группа по значению - PullRequest
       1

XSLT группа по значению

0 голосов
/ 13 сентября 2011

У меня есть XML-документ

<Contracts>   
    <Contract>
        <F1>key1</F1>
        <F2>2345</F2>
        <F3>val</F3>
        <F4>dal</F4>
    </Contract>
    <Contract>
        <F1>key1</F1>
        <F2>34562</F2>
        <F3>val</F3>
        <F4>dal</F4>
    </Contract>
    <Contract>
        <F1>key2</F1>
        <F2>416235</F2>
        <F3>val</F3>
        <F4>sal</F4>
    </Contract> 
    <Contract>
        <F1>key2</F1>
        <F2>416235</F2>
        <F3>val</F3>
        <F4>sal</F4>
    </Contract> 
    <Contract>
        <F1>key2</F1>
        <F2>41575</F2>
        <F3>val</F3>
        <F4>bal</F4>
    </Contract>
</Contracts>

Мне нужно сгруппировать эти контракты по Contracts/Contract/F1 (key1, key2), чтобы получить такой результат:

<Contracts>
    <Set>
        <Contract>
            <F1>key1</F1>
            <F2>2345</F2>
            <F3>val</F3>
            <F4>dal</F4>
        </Contract>
        <Contract>
            <F1>key1</F1>
            <F2>34562</F2>
            <F3>val</F3>
            <F4>dal</F4>
        </Contract>
    <Set>
    <Set>
        <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
        </Contract> 
        <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
        </Contract> 
        <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
        </Contract>
   </Set>
</Contracts>

Как это сделатьXSLT?

Ответы [ 2 ]

4 голосов
/ 13 сентября 2011

I.Решение XSLT 1.0 (мюнхенская группировка, нет xsl:for-each):

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

 <xsl:key name="kContrByF1" match="Contract" use="F1"/>

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

 <xsl:template match=
  "Contract[not(generate-id()
               =
                generate-id(key('kContrByF1', F1)[1])
                )
            ]"/>

 <xsl:template match="Contract">
  <Contract>
   <Set>
    <xsl:copy-of select="key('kContrByF1', F1)"/>
   </Set>
  </Contract>
 </xsl:template>
</xsl:stylesheet>

, когда это преобразование применяется к предоставленному документу XML :

<Contracts>
    <Contract>
        <F1>key1</F1>
        <F2>2345</F2>
        <F3>val</F3>
        <F4>dal</F4>
    </Contract>
    <Contract>
        <F1>key1</F1>
        <F2>34562</F2>
        <F3>val</F3>
        <F4>dal</F4>
    </Contract>
    <Contract>
        <F1>key2</F1>
        <F2>416235</F2>
        <F3>val</F3>
        <F4>sal</F4>
    </Contract>
    <Contract>
        <F1>key2</F1>
        <F2>416235</F2>
        <F3>val</F3>
        <F4>sal</F4>
    </Contract>
    <Contract>
        <F1>key2</F1>
        <F2>41575</F2>
        <F3>val</F3>
        <F4>bal</F4>
    </Contract>
</Contracts>

желаемый, правильный результат получается :

<Contracts>
   <Contract>
      <Set>
         <Contract>
            <F1>key1</F1>
            <F2>2345</F2>
            <F3>val</F3>
            <F4>dal</F4>
         </Contract>
         <Contract>
            <F1>key1</F1>
            <F2>34562</F2>
            <F3>val</F3>
            <F4>dal</F4>
         </Contract>
      </Set>
   </Contract>
   <Contract>
      <Set>
         <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
         </Contract>
         <Contract>
            <F1>key2</F1>
            <F2>416235</F2>
            <F3>val</F3>
            <F4>sal</F4>
         </Contract>
         <Contract>
            <F1>key2</F1>
            <F2>41575</F2>
            <F3>val</F3>
            <F4>bal</F4>
         </Contract>
      </Set>
   </Contract>
</Contracts>

II.Решение XSLT 2.0 :

 <xsl:template match="/*">
     <Contracts>
       <xsl:for-each-group select="Contract" group-by="F1">
         <Contract>
          <Set>
            <xsl:sequence select="current-group()"/>
          </Set>
         </Contract>
       </xsl:for-each-group>
     </Contracts>
 </xsl:template>
</xsl:stylesheet>

Опять же, когда это преобразование применяется к тому же XML-документу (см. Выше), получается тот же правильный результат.

Примечание:

  1. Использование инструкции xsl:for-each-group.

  2. Использование функции current-group().

1 голос
/ 13 сентября 2011

Используйте ключ XSL и мюнхенскую группировку.

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

  <xsl:key name="kContract" match="Contract" use="F1" />

  <xsl:template match="Contracts">
    <xsl:copy>
      <xsl:for-each select="
        Contract[
          generate-id() = generate-id(key('kContract', F1)[1])
        ]
      ">
        <Set>
          <xsl:copy-of select="key('kContract', F1)" />
        </Set>
      </xsl:for-each>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Эта таблица стилей производит именно то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...