xsl-list
[Top] [All Lists]

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

2012-06-19 09:33:08
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>
--~--