/ / Grupowanie i łączenie dwóch kontaktów w XSLT1.0 - xml, xslt, xpath

Grupowanie i łączenie dwóch kontaktów w XSLT1.0 - xml, xslt, xpath

To jest mój plik xml:

<?xml version="1.0" encoding="utf-8"?>
<CONTACTS>

<CONTACT>
<FirstName>Arun</FirstName>
<LastName>Arun_Neelam</LastName>
<Email>nuraaa_iceee@yahoo.co.in</Email>
</CONTACT>

<CONTACT>
<FirstName>Arun</FirstName>
<LastName>Arun_Neelam</LastName>
<Email>nuraaa_iceee@gmail.com</Email>

</CONTACT>
</CONTACTS>

1.Jak mogę połączyć powyższe 2 kontakty jako pojedynczy kontakt należący do tej samej osoby

Chciałbym mieć wyjście takie jak to:

<?xml version="1.0" encoding="windows-1250"?>
<CONTACTS>
<CONTACT>
<FirstName>Arun</FirstName>
<LastName>Arun_Neelam</LastName>
<Email>nuraaa_iceee@gmail.com</Email>
<Email>nuraaa_iceee@yahoo.co.in</Email>
</CONTACT>
</CONTACTS>

Nie jestem pewien, czy mogę to zrobić current-group() and current-grouping-key(). Bardzo dziękuję za wsparcie.

user639175, pomógł w rozwiązaniu tego problemu, a jego rozwiązanie działa, ale nie daje pożądanego rezultatu. Więc zmieniłem pytanie w prosty sposób.

Uwaga: sformatowałem pytanie jeszcze raz, aby uniknąć nieporozumień w tym samym wątku.

Odpowiedzi:

0 dla odpowiedzi № 1
<?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" version="1.0"  encoding="windows-1250" indent="yes" />

<xsl:key name="groupName" match="//CONTACTS/CONTACT" use="concat(FirstName, LastName)" />

<xsl:template match="CONTACTS">

<CONTACTS>
<xsl:for-each select="//CONTACTS/CONTACT[generate-id() = generate-id( key("groupName", concat(FirstName, LastName))   [1] ) ]" >
<xsl:sort select="CONTACT/EMail"  />

<xsl:call-template name="group">
<xsl:with-param name="k1" select="FirstName" />
<xsl:with-param name="k2" select="LastName" />
</xsl:call-template>

</xsl:for-each>
</CONTACTS>
</xsl:template>

<xsl:template name="group">
<xsl:param name="k1" />
<xsl:param name="k2" />

<CONTACT>
<xsl:for-each select="//CONTACTS/CONTACT[FirstName = $k1][LastName = $k2][1]">

<xsl:copy-of select="FirstName" />
<xsl:copy-of select="LastName" />
<!-- here we have the first Email -->
<xsl:copy-of select="EMail" />

</xsl:for-each>
<xsl:for-each select="//CONTACTS/CONTACT[FirstName = $k1][LastName = $k2][position() &gt; 1]">
<!-- here we have the next Email -->

<xsl:copy-of select="EMail" />

</xsl:for-each>
</CONTACT>

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

Powinno działać :)


2 dla odpowiedzi nr 2

Przy użyciu standardowej techniki grupowania potrzebujesz tylko dwóch szablonów (bez pętli, bez params):

  • Użyć klucz złożony zbierać KONTAKT przez Imię i Drugie imię.
  • Następnie zastosuj szablony do jednego KONTAKT dla każdej grupy.
  • Na koniec pobierz E-mail węzły z klucza.

Twoja ostateczna transformacja:

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

<xsl:key name="k_Contacts"
match="CONTACTS/CONTACT"
use="concat(FirstName,LastName)"/>

<xsl:template match="CONTACTS">
<xsl:copy>
<xsl:apply-templates select="CONTACT[generate-id()=
generate-id(key("k_Contacts",concat(FirstName,LastName))[1])]"/>
</xsl:copy>
</xsl:template>

<xsl:template match="CONTACT">
<xsl:copy>
<xsl:copy-of select="FirstName | LastName"/>
<xsl:copy-of select="key("k_Contacts",concat(FirstName,LastName))
/Email"/>
</xsl:copy>
</xsl:template>

</xsl:stylesheet>

W XSLT 2.0 możesz użyć xsl:for-each-group; po prostu zastąp

<xsl:apply-templates select="CONTACT[generate-id()=
generate-id(key("k_Contacts",concat(FirstName,LastName))[1])]"/>

z:

    <xsl:for-each-group select="CONTACT" group-by="concat(FirstName,LastName)">
<xsl:apply-templates select="current-group()[1]"/>
</xsl:for-each-group>

0 dla odpowiedzi № 3
<?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" version="1.0"  encoding="windows-1250" indent="yes" />

<xsl:key name="groupName" match="//CONTACTS/CONTACT" use="concat(FirstName, LastName)" />

<xsl:template match="CONTACTS">

<CONTACTS>
<xsl:for-each select="//CONTACTS/CONTACT[generate-id() = generate-id( key("groupName", concat(FirstName, LastName))   [1] ) ]" >
<xsl:sort select="CONTACT/EMail"  />

<xsl:call-template name="group">
<xsl:with-param name="k1" select="FirstName" />
<xsl:with-param name="k2" select="LastName" />
</xsl:call-template>

</xsl:for-each>
</CONTACTS>
</xsl:template>

<xsl:template name="group">
<xsl:param name="k1" />
<xsl:param name="k2" />


<xsl:for-each select="//CONTACTS/CONTACT[FirstName = $k1][LastName = $k2][1]">

<xsl:copy-of select="." />

</xsl:for-each>

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

Nie wykluczyłem Arun - ponieważ twój exmaple ma wadę? w przeciwnym razie działa :)