Pretty easy, overall. Mainly you need to remember that you can register
multiple node-set matches under a single key name, and retrieve them all at the
same time through one key() call. This allows you to do Muenchian grouping over
multiple node-sets whose nodes have similar but not identical structure. After
you have the groups, it's just a matter of choosing which element you retrieve
for grouping and for the medicinalproduct node. The self:: axis ends up being
slightly more succinct than a predicate that checks name(). It's repeated three
times here; I don't know if that starts to be a case for pulling out the string
itself into an XML entity. YMMV.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" indent="yes" omit-xml-declaration="yes" />
<xsl:key name="drug" match="DrugSafetyReportDrug" use="MedicinalProductName"
/>
<xsl:key name="drug" match="DrugSafetyReportMedicalDevice"
use="MedicalDeviceName" />
<xsl:variable name="drugs" select="//DrugSafetyReportDrug |
//DrugSafetyReportMedicalDevice" />
<xsl:template match="/*">
<Root>
<xsl:for-each select="$drugs[generate-id(key('drug',
self::DrugSafetyReportDrug/MedicinalProductName |
self::DrugSafetyReportMedicalDevice/MedicalDeviceName)) = generate-id()]">
<Drug>
<medicinalproduct>
<xsl:value-of
select="self::DrugSafetyReportDrug/MedicinalProductName |
self::DrugSafetyReportMedicalDevice/MedicalDeviceName" />
</medicinalproduct>
<xsl:copy-of select="key('drug',
self::DrugSafetyReportDrug/MedicinalProductName |
self::DrugSafetyReportMedicalDevice/MedicalDeviceName)/*[not(self::MedicinalProductName
or self::MedicalDeviceName)]" />
</Drug>
</xsl:for-each>
</Root>
</xsl:template>
</xsl:stylesheet>
XSLT2 would be just slightly more convenient here, with <xsl:for-each-group
select="//DrugSafetyReportDrug | //DrugSafetyReportMedicalDevice"
group-by="self::DrugSafetyReportDrug/MedicinalProductName |
self::DrugSafetyReportMedicalDevice/MedicalDeviceName">, and then using
current-group() instead of calling key() again... but the underlying logic
would stay the same.
~ Scott
-----Original Message-----
From: Amit Agarwal [mailto:aagarwal123(_at_)gmail(_dot_)com]
Sent: Tuesday, June 19, 2012 8:12 AM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com;
xsl-list-help(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] How to do this unique grouping on XML using XSLT 1.0
My input xml looks like:
Root>
<ReportDrugSafetyReport>
<DrugSafetyReportPatient>
<DrugSafetyReportDrug>
<MedicinalProductName>BPM Infra</MedicinalProductName>
<ObtainedCountryCode>US</ObtainedCountryCode>
</DrugSafetyReportDrug>
<DrugSafetyReportDrug>
<MedicinalProductName>Multistandard VCR</MedicinalProductName>
<ObtainedCountryCode>UK</ObtainedCountryCode>
</DrugSafetyReportDrug>
<DrugSafetyReportDrug>
<MedicinalProductName>Pharmaceuticals</MedicinalProductName>
<ObtainedCountryCode>IN</ObtainedCountryCode>
</DrugSafetyReportDrug>
</DrugSafetyReportPatient>
<DrugSafetyReportMedicalDevice>
<MedicalDeviceName>BPM Infra</MedicalDeviceName>
<DeviceProductCode>1234</DeviceProductCode>
</DrugSafetyReportMedicalDevice>
<DrugSafetyReportMedicalDevice>
<MedicalDeviceName>Different Product name</MedicalDeviceName>
<DeviceProductCode>456</DeviceProductCode>
</DrugSafetyReportMedicalDevice>
</ReportDrugSafetyReport>
</Root>
And My target xml is:
<Root>
<Drug>
<medicinalproduct>BPM Infra</medicinalproduct>
<ObtainedCountryCode>US</ObtainedCountryCode>
<DeviceProductCode>1234</DeviceProductCode>
</Drug>
<Drug>
<medicinalproduct>Multistandard VCR</medicinalproduct>
<ObtainedCountryCode>UK</ObtainedCountryCode>
</Drug>
<Drug>
<medicinalproduct>Pharmaceuticals</medicinalproduct>
<ObtainedCountryCode>IN</ObtainedCountryCode>
</Drug>
<Drug>
<medicinalproduct>Different Product name</medicinalproduct>
<DeviceProductCode>456</DeviceProductCode>
</Drug>
</Root>
Input xml contains two unbounded elements DrugSafetyReportDrug and
DrugSafetyReportMedicalDevice. Both of these elements belongs to different
parent elements, e.g.
<root>ReportDrugSafetyReport/
DrugSafetyReportPatient/DrugSafetyReportDrug and
<root>/ReportDrugSafetyReport/DrugSafetyReportMedicalDevice
Each of these elements has a set of child elements. Out of which,
MedicinalProductName is child element of DrugSafetyReportDrug
(DrugSafetyReportDrug/MedicinalProductName) and MedicalDeviceName is child
element of DrugSafetyReportMedicalDevice
(DrugSafetyReportMedicalDevice/MedicalDeviceName).
Target xml has an unbounded element: drug.
If MedicinalProductName = MedicalDeviceName then DrugSafetyReportDrug and
DrugSafetyReportMedicalDevice should be grouped to a single drug element (in
the target xml). Otherwise, there would be a separate drug element for each
DrugSafetyReportDrug and DrugSafetyReportMedicalDevice.
Thanks for your help!.
Thanks,
Amit
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--