gasparuff
gasparuff

Reputation: 2295

XSLT can't figure out how to group properly

I have the following XML file, which is exported from an Oracle-DB: http://pastebin.com/0yPcc7HT

I need to transform it to the following structure:

<?xml version="1.0" encoding="UTF-8"?>
<ROWSET>
   <KUNDE>
      <KUNDENNR>59957</KUNDENNR>
      <ANSPRECHPARTNERS>
         <ANSPRECHPARTNER>
            <ANSPRECHNR>3</ANSPRECHNR>
            <FUNKTION>lfd. Kontakt,                 </FUNKTION>
            <VORNAME>Some                         </VORNAME>
            <NACHNAME>Dude                     </NACHNAME>
            <ABTEILUNG>Einkauf                       </ABTEILUNG>
            <EMAIL>[email protected]</EMAIL>
            <TELEFON>123456789</TELEFON>
            <PREISLISTEN>
               <PREISLISTE>Katalog                       </PREISLISTE>
               <PREISLISTE>Y OO                          </PREISLISTE>
               <PREISLISTE>Kopierpapier "A"              </PREISLISTE>
               <PREISLISTE>Aktion Internet               </PREISLISTE>
               <PREISLISTE>Tinte Toner "H"               </PREISLISTE>
               <PREISLISTE>News Internet                 </PREISLISTE>
            </PREISLISTEN>
            <SPESEN>
               <SPESE>Sonderbeschaffungskosten      </SPESE> 
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
            </SPESEN>
         </ANSPRECHPARTNER>
         <ANSPRECHPARTNER>
            <ANSPRECHNR>1</ANSPRECHNR>
            <FUNKTION>Sachbearbeitung               </FUNKTION>
            <VORNAME>Another                      </VORNAME>
            <NACHNAME>Dudarina                    </NACHNAME>
            <ABTEILUNG>Einkauf                       </ABTEILUNG>
            <EMAIL>[email protected]</EMAIL>
            <TELEFON>+43 17007 32102</TELEFON>
            <PREISLISTEN>
               <PREISLISTE>Katalog                       </PREISLISTE>
               <PREISLISTE>Y OO                          </PREISLISTE>
               <PREISLISTE>Kopierpapier "A"              </PREISLISTE>
               <PREISLISTE>Aktion Internet               </PREISLISTE>
               <PREISLISTE>Tinte Toner "H"               </PREISLISTE>
               <PREISLISTE>News Internet                 </PREISLISTE>
            </PREISLISTEN>
            <SPESEN>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
            </SPESEN>
         </ANSPRECHPARTNER>
      </ANSPRECHPARTNERS>
   </KUNDE>
</ROWSET>

I have tried different things for many hours now, but I just can't find out how to do it correctly. This is how my XSLT file looks like:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">
    <xsl:output method="xml" indent="yes" />
    <xsl:key name="rowsByKDNR" match="ROW" use="concat(KUNDENNR, '+', ANSPRECHNR)"></xsl:key>

    <xsl:template match="ROWSET">

        <ROWSET>
            <xsl:for-each-group select="ROW" group-by="KUNDENNR">
                <KUNDE>
                    <xsl:copy-of select="KUNDENNR" />
                    <ANSPRECHPARTNERS>
                        <xsl:for-each select="current-group()[count(. | key('rowsByMonth', concat(KUNDENNR, '+', ANSPRECHNR))[1]) = 1]">
                            <ANSPRECHPARTNER>
                                <xsl:copy-of select="ANSPRECHNR" />
                                <xsl:copy-of select="FUNKTION" />
                                <xsl:copy-of select="VORNAME" />
                                <xsl:copy-of select="NACHNAME" />
                                <xsl:copy-of select="ABTEILUNG" />
                                <xsl:copy-of select="EMAIL" />
                                <xsl:copy-of select="TELEFON" />
                                <PREISLISTEN>
                                    <xsl:for-each select="key('rowsByKDNR', concat(KUNDENNR, '+', ANSPRECHNR))">
                                            <xsl:copy-of select="PREISLISTE" />
                                    </xsl:for-each>
                                </PREISLISTEN>
                                <SPESEN>
                                    <xsl:for-each select="key('rowsByKDNR', concat(KUNDENNR, '+', ANSPRECHNR))">
                                        <SPESE>
                                            <xsl:value-of select="SPESEN" />
                                        </SPESE>
                                    </xsl:for-each>
                                </SPESEN>
                            </ANSPRECHPARTNER>
                        </xsl:for-each>
                    </ANSPRECHPARTNERS>
                </KUNDE>
            </xsl:for-each-group>

        </ROWSET>
    </xsl:template></xsl:stylesheet>

But this gives me the following result:

<?xml version="1.0" encoding="UTF-8"?>
<ROWSET>
   <KUNDE>
      <KUNDENNR>59957</KUNDENNR>
      <ANSPRECHPARTNERS>
         <ANSPRECHPARTNER>
            <ANSPRECHNR>3</ANSPRECHNR>
            <FUNKTION>lfd. Kontakt,                 </FUNKTION>
            <VORNAME>Some                         </VORNAME>
            <NACHNAME>Dude                     </NACHNAME>
            <ABTEILUNG>Einkauf                       </ABTEILUNG>
            <EMAIL>[email protected]</EMAIL>
            <TELEFON>123456789</TELEFON>
            <PREISLISTEN>
               <PREISLISTE>Katalog                       </PREISLISTE>
               <PREISLISTE>Y OO                          </PREISLISTE>
               <PREISLISTE>Kopierpapier "A"              </PREISLISTE>
               <PREISLISTE>Aktion Internet               </PREISLISTE>
               <PREISLISTE>Tinte Toner "H"               </PREISLISTE>
               <PREISLISTE>News Internet                 </PREISLISTE>
               <PREISLISTE>Katalog                       </PREISLISTE>
               <PREISLISTE>Y OO                          </PREISLISTE>
               <PREISLISTE>Kopierpapier "A"              </PREISLISTE>
               <PREISLISTE>Aktion Internet               </PREISLISTE>
               <PREISLISTE>Tinte Toner "H"               </PREISLISTE>
               <PREISLISTE>News Internet                 </PREISLISTE>
            </PREISLISTEN>
            <SPESEN>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
            </SPESEN>
         </ANSPRECHPARTNER>
         <ANSPRECHPARTNER>
            <ANSPRECHNR>1</ANSPRECHNR>
            <FUNKTION>Sachbearbeitung               </FUNKTION>
            <VORNAME>Another                      </VORNAME>
            <NACHNAME>Dudarina                    </NACHNAME>
            <ABTEILUNG>Einkauf                       </ABTEILUNG>
            <EMAIL>[email protected]</EMAIL>
            <TELEFON>+43 17007 32102</TELEFON>
            <PREISLISTEN>
               <PREISLISTE>Katalog                       </PREISLISTE>
               <PREISLISTE>Y OO                          </PREISLISTE>
               <PREISLISTE>Kopierpapier "A"              </PREISLISTE>
               <PREISLISTE>Aktion Internet               </PREISLISTE>
               <PREISLISTE>Tinte Toner "H"               </PREISLISTE>
               <PREISLISTE>News Internet                 </PREISLISTE>
               <PREISLISTE>Katalog                       </PREISLISTE>
               <PREISLISTE>Y OO                          </PREISLISTE>
               <PREISLISTE>Kopierpapier "A"              </PREISLISTE>
               <PREISLISTE>Aktion Internet               </PREISLISTE>
               <PREISLISTE>Tinte Toner "H"               </PREISLISTE>
               <PREISLISTE>News Internet                 </PREISLISTE>
            </PREISLISTEN>
            <SPESEN>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
            </SPESEN>
         </ANSPRECHPARTNER>
      </ANSPRECHPARTNERS>
   </KUNDE>
</ROWSET>

Elements in PREISLISTEN and SPESEN just appear too often. What am I doing wrong and what do I need to change in order to make it work?

Thank you in advance

Upvotes: 0

Views: 115

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167716

First of all, assuming you can use an XSLT 2.0 processor and for-each-group, I wouldn't bother with keys and Muenchian grouping, I would simply nest the for-each-group instructions as needed.

Based on that, when Saxon 9.5 applies the stylesheet

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

  <xsl:template match="ROWSET">

    <ROWSET>
      <xsl:for-each-group select="ROW" group-by="KUNDENNR">
        <KUNDE>
          <xsl:copy-of select="KUNDENNR" />
          <ANSPRECHPARTNERS>
            <xsl:for-each-group select="current-group()" group-by="ANSPRECHNR">
              <ANSPRECHPARTNER>
                <xsl:copy-of select="ANSPRECHNR, FUNKTION, VORNAME, NACHNAME,
                                                    ABTEILUNG, EMAIL, TELEFON" />
                <PREISLISTEN>
                  <xsl:for-each-group select="current-group()" group-by="PREISLISTE">
                    <xsl:copy-of select="PREISLISTE"/>
                  </xsl:for-each-group>
                </PREISLISTEN>
                <SPESEN>
                  <xsl:for-each-group select="current-group()" group-by="SPESEN">
                    <SPESE>
                      <xsl:value-of select="current-grouping-key()" />
                    </SPESE>
                  </xsl:for-each-group>
                </SPESEN>
              </ANSPRECHPARTNER>
            </xsl:for-each-group>
          </ANSPRECHPARTNERS>
        </KUNDE>
      </xsl:for-each-group>

    </ROWSET>
  </xsl:template>

</xsl:stylesheet>

to the input you have linked to it creates the following result

<?xml version="1.0" encoding="UTF-8"?>
<ROWSET>
   <KUNDE>
      <KUNDENNR>59957</KUNDENNR>
      <ANSPRECHPARTNERS>
         <ANSPRECHPARTNER>
            <ANSPRECHNR>3</ANSPRECHNR>
            <FUNKTION>lfd. Kontakt,                 </FUNKTION>
            <VORNAME>Some                         </VORNAME>
            <NACHNAME>Dude                     </NACHNAME>
            <ABTEILUNG>Einkauf                       </ABTEILUNG>
            <EMAIL>[email protected]</EMAIL>
            <TELEFON>123456789</TELEFON>
            <PREISLISTEN>
               <PREISLISTE>Katalog                       </PREISLISTE>
               <PREISLISTE>Y OO                          </PREISLISTE>
               <PREISLISTE>Kopierpapier "A"              </PREISLISTE>
               <PREISLISTE>Aktion Internet               </PREISLISTE>
               <PREISLISTE>Tinte Toner "H"               </PREISLISTE>
               <PREISLISTE>News Internet                 </PREISLISTE>
            </PREISLISTEN>
            <SPESEN>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
            </SPESEN>
         </ANSPRECHPARTNER>
         <ANSPRECHPARTNER>
            <ANSPRECHNR>1</ANSPRECHNR>
            <FUNKTION>Sachbearbeitung               </FUNKTION>
            <VORNAME>Another                      </VORNAME>
            <NACHNAME>Dudarina                    </NACHNAME>
            <ABTEILUNG>Einkauf                       </ABTEILUNG>
            <EMAIL>[email protected]</EMAIL>
            <TELEFON>+43 17007 32102</TELEFON>
            <PREISLISTEN>
               <PREISLISTE>Katalog                       </PREISLISTE>
               <PREISLISTE>Y OO                          </PREISLISTE>
               <PREISLISTE>Kopierpapier "A"              </PREISLISTE>
               <PREISLISTE>Aktion Internet               </PREISLISTE>
               <PREISLISTE>Tinte Toner "H"               </PREISLISTE>
               <PREISLISTE>News Internet                 </PREISLISTE>
            </PREISLISTEN>
            <SPESEN>
               <SPESE>Sonderbeschaffungskosten      </SPESE>
               <SPESE>MM-Zuschlag55 3.6             </SPESE>
            </SPESEN>
         </ANSPRECHPARTNER>
      </ANSPRECHPARTNERS>
   </KUNDE>
</ROWSET>

Upvotes: 1

Related Questions