xsl-list
[Top] [All Lists]

Re: [xsl] How to do this unique grouping on XML using XSLT 1.0

2012-06-19 10:22:59
Hi Scott,

Thanks a lot for your prompt response.

Your input has helped me to resolve the issue to a great extent.

Highly Appreciate your support !

Thanks,
Amir

On Tue, Jun 19, 2012 at 8:02 PM, Scott Trenda 
<Scott(_dot_)Trenda(_at_)oati(_dot_)net> wrote:
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>
--~--


--~------------------------------------------------------------------
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>
--~--