Need element to appear only once

Here should go questions about transforming XML with XSLT and FOP.
gjledger2k
Posts: 16
Joined: Tue Aug 01, 2006 2:56 am
Location: Chicago

Need element to appear only once

Post by gjledger2k »

Hi,
I'm hoping I can do this without scripting. I imported an Excel document that includes a list of doctors, their specialty, and the county they work in.

The code after importing:

Code: Select all

<?xml version="1.0" encoding="UTF-8"?>
<Root>
<record>
<Provider_Type_Specialty_>Family Practice</Provider_Type_Specialty_>
<Provider_LName>Lo</Provider_LName>
<Provider_FName>Jennifer Jose</Provider_FName>
<Credentials>MD</Credentials>
<County>Duval</County>
</record>
<record>
<Provider_Type_Specialty_>General Practice</Provider_Type_Specialty_>
<Provider_LName>Barsoum</Provider_LName>
<Provider_FName>Nageh</Provider_FName>
<Credentials>MD</Credentials>
<County>Brevard</County>
</record>
<record>
<Provider_Type_Specialty_>Neurological Surgery</Provider_Type_Specialty_>
<Provider_LName>Razack </Provider_LName>
<Provider_FName>Nizam</Provider_FName>
<Credentials>MD</Credentials>
<County>Seminole</County>
</record>
<record>
<Provider_Type_Specialty_>Neurological Surgery</Provider_Type_Specialty_>
<Provider_LName>Villalobos </Provider_LName>
<Provider_FName>Hunaldo</Provider_FName>
<Credentials>MD</Credentials>
<County>Osceola</County>
</record>
<record>
<Provider_Type_Specialty_>Obstetrics And Gynecology</Provider_Type_Specialty_>
<Provider_LName>Marler </Provider_LName>
<Provider_FName>David</Provider_FName>
<Credentials>MD</Credentials>
<County>Lake</County>
</record>
<record>
<Provider_Type_Specialty_>Orthopedic Surgery</Provider_Type_Specialty_>
<Provider_LName>Conaughty </Provider_LName>
<Provider_FName>Jason</Provider_FName>
<Credentials>MD</Credentials>
<County>Seminole</County>
</record>
<record>
<Provider_Type_Specialty_>Pediatric Critical Care Medicine</Provider_Type_Specialty_>
<Provider_LName>Davis </Provider_LName>
<Provider_FName>Jennifer</Provider_FName>
<Credentials>MD</Credentials>
<County>Palm Beach</County>
</record>
<record>
<Provider_Type_Specialty_>Pediatrics</Provider_Type_Specialty_>
<Provider_LName>Baez Rivera </Provider_LName>
<Provider_FName>Emilio</Provider_FName>
<Credentials>MD</Credentials>
<County>Broward</County>
</record>
<record>
<Provider_Type_Specialty_>Pediatrics</Provider_Type_Specialty_>
<Provider_LName>Cedres </Provider_LName>
<Provider_FName>Carmelo</Provider_FName>
<Credentials>MD</Credentials>
<County>Duval</County>
</record>
<record>
<Provider_Type_Specialty_>Pediatrics</Provider_Type_Specialty_>
<Provider_LName>Klenck </Provider_LName>
<Provider_FName>Claudia</Provider_FName>
<Credentials>MD</Credentials>
<County>Duval</County>
</record>
<record>
<Provider_Type_Specialty_>Pediatrics</Provider_Type_Specialty_>
<Provider_LName>Sabbagh </Provider_LName>
<Provider_FName>Radwan</Provider_FName>
<Credentials>MD</Credentials>
<County>Laurens</County>
</record>
<record>
<Provider_Type_Specialty_>Chiropractor</Provider_Type_Specialty_>
<Provider_LName>Shontz</Provider_LName>
<Provider_FName>Michael</Provider_FName>
<Credentials>DC</Credentials>
<County>Pasco</County>
</record>
<record>
<Provider_Type_Specialty_>Speech Pathology</Provider_Type_Specialty_>
<Provider_LName>Perfect Speech</Provider_LName>
<Provider_FName/>
<Credentials/>
<County>Dade</County>
</record>
<record>
<Provider_Type_Specialty_>Chiropractor</Provider_Type_Specialty_>
<Provider_LName>Accurso III</Provider_LName>
<Provider_FName>Joseph</Provider_FName>
<Credentials>DC</Credentials>
<County>Dade</County>
</record>
<record>
<Provider_Type_Specialty_>Occupational and Physical Therapy</Provider_Type_Specialty_>
<Provider_LName>Hohman Rehab And Sports Therapy</Provider_LName>
<Provider_FName/>
<Credentials/>
<County>Lake</County>
</record>
<record>
<Provider_Type_Specialty_>Physician Psychiatry</Provider_Type_Specialty_>
<Provider_LName>Cely</Provider_LName>
<Provider_FName>Maria S.</Provider_FName>
<Credentials>MD</Credentials>
<County>Orange</County>
</record>
<record>
<Provider_Type_Specialty_>Physician Psychiatry</Provider_Type_Specialty_>
<Provider_LName>Diaz </Provider_LName>
<Provider_FName>Enrique</Provider_FName>
<Credentials>MD</Credentials>
<County>Dade</County>
</record>
<record>
<Provider_Type_Specialty_>Psychologist</Provider_Type_Specialty_>
<Provider_LName>Hartman</Provider_LName>
<Provider_FName>Michael C.</Provider_FName>
<Credentials>LCSW</Credentials>
<County>Highlands</County>
</record>
<record>
<Provider_Type_Specialty_>Nurse w Prescriptive Authority</Provider_Type_Specialty_>
<Provider_LName>Nemati</Provider_LName>
<Provider_FName>Sakinah A.</Provider_FName>
<Credentials>ARNP</Credentials>
<County>Duval</County>
</record>
</Root>
I am able to transform this so that the doctors are sorted first by County, then by their specialty (Provider_Type_Specialty) then by their names. Here is the transform:

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="Root">
<xsl:apply-templates>
<xsl:sort select="County"/>
<xsl:sort select="Provider_Type_Specialty_"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="record">
<xsl:if test="//County">
<xsl:apply-templates select="County"/>
</xsl:if>
<xsl:call-template name="Newline"/>
<xsl:apply-templates select="Provider_Type_Specialty_"/>
<xsl:call-template name="Newline"/>
<xsl:value-of select="Provider_FName"/><xsl:text> </xsl:text><xsl:value-of
select="Provider_LName"/>, <xsl:value-of select="Credentials"/>
<xsl:call-template name="Newline"/>
<xsl:call-template name="Newline"/>
</xsl:template>
<xsl:template name="Newline">
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:transform>
And that gives me this:

Brevard
General Practice
Nageh Barsoum, MD

Broward
Pediatrics
Emilio Baez Rivera, MD

Dade
Chiropractor
Joseph Accurso III, DC

Dade
Physician Psychiatry
Enrique Diaz, MD

Dade
Speech Pathology
Perfect Speech,

Duval
Family Practice
Jennifer Jose Lo, MD

Duval
Nurse w Prescriptive Authority
Sakinah A. Nemati, ARNP

Duval
Pediatrics
Carmelo Cedres, MD

Duval
Pediatrics
Claudia Klenck, MD

...etc.

What I need is for the county to appear only once, and the provider specialty by county to appear only once. So it should look like this:

Brevard
General Practice
Nageh Barsoum, MD

Broward
Pediatrics
Emilio Baez Rivera, MD

Dade (!--county appears only once for each provider)
Chiropractor
Joseph Accurso III, DC

Physician Psychiatry
Enrique Diaz, MD

Speech Pathology
Perfect Speech,

Duval (county appears only once for each provider)
Family Practice
Jennifer Jose Lo, MD

Nurse w Prescriptive Authority
Sakinah A. Nemati, ARNP

Pediatrics (!--specialty appears only once for each provider with that specialty)
Carmelo Cedres, MD
Claudia Klenck, MD

etc...

I tried using position() to reference just the first instance of the county name, but I found that only the cardinal number of the record changes, while the county's position is always 1. I also tried an if test, but really was just making the same mistake another way.

So, any suggestions as to how to accomplish this. (As I may have pointed out before, I am not a programmer.) Thanks.
george
Site Admin
Posts: 2095
Joined: Thu Jan 09, 2003 2:58 pm

Re: Need element to appear only once

Post by george »

XSLT 2.0 provides specific support for grouping. A simple stylesheet like below gets you the desired result

Code: Select all


<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="text"/>
<xsl:template match="Root">
<xsl:for-each-group select="record" group-by="County">
<xsl:value-of select="current-grouping-key()"/>
<xsl:text>&#10;</xsl:text>
<xsl:for-each-group select="current-group()" group-by="Provider_Type_Specialty_">
<xsl:value-of select="current-grouping-key()"/>
<xsl:text>&#10;</xsl:text>
<xsl:for-each select="current-group()">
<xsl:value-of select="Provider_FName"/>
<xsl:text> </xsl:text>
<xsl:value-of select="Provider_LName"/>
<xsl:text>, </xsl:text>
<xsl:value-of select="Credentials"/>
<xsl:text>&#10;&#10;</xsl:text>
</xsl:for-each>
</xsl:for-each-group>
<xsl:text>&#10;</xsl:text>
</xsl:for-each-group>
</xsl:template>
</xsl:transform>
Just make sure you use Saxon 9 as XSLT processor.

Best Regards,
George
George Cristian Bina
gjledger2k
Posts: 16
Joined: Tue Aug 01, 2006 2:56 am
Location: Chicago

Re: Need element to appear only once

Post by gjledger2k »

Thank you thank you. I guess it is time I looked at XSLT 2.0.
Post Reply