[xsl] Deepening a flat structure and numbering nodes

Subject: [xsl] Deepening a flat structure and numbering nodes
From: "Rick Quatro" <rick@xxxxxxxxxxxxxx>
Date: Sat, 10 Aug 2013 08:53:25 -0400
Hi All,

Here is my input XML:

<?xml version="1.0" encoding="UTF-8"?>
<Cases>
    <Story>
        <Category>Category: Subcategory</Category>
        <CaseTitle>Title One</CaseTitle>
        <Institution>Institution One</Institution >
        <Author>Authors One</Author>
        <History>History One</History>
        <DifferentialDiagnosis>Sick</DifferentialDiagnosis>
        <DifferentialDiagnosis>Sicker</DifferentialDiagnosis>
        <DifferentialDiagnosis>Sickest</DifferentialDiagnosis>
        <TeachingPoint>Point1</TeachingPoint>
        <TeachingPoint>Point2</TeachingPoint>
        <Category>Category One: Subcategory</Category>
        <CaseTitle>Title Two</CaseTitle>
        <Institution>Title Two</Institution >
        <Author>Author Two</Author>
        <History>History Two</History>
        <DifferentialDiagnosis>Sick</DifferentialDiagnosis>
        <DifferentialDiagnosis>Sicker</DifferentialDiagnosis>
        <DifferentialDiagnosis>Sickest</DifferentialDiagnosis>
        <TeachingPoint>Point1</TeachingPoint>
        <TeachingPoint>Point2</TeachingPoint>
    </Story>
</Cases>

I want to organize the data in a deeper structure like this:

<?xml version="1.0" encoding="UTF-8"?>
<data>
   <newRecord>
      <Category>Category</Category>
      <Subcategory>Subcategory</Subcategory>
      <Case>1</Case>
      <CaseTitle>Title One</CaseTitle>
      <Institution>Institution One</Institution>
      <Author>Authors One</Author>
      <History>History One</History>
      <DifferentialDiagnosis>Sick</DifferentialDiagnosis>
      <DifferentialDiagnosis>Sicker</DifferentialDiagnosis>
      <DifferentialDiagnosis>Sickest</DifferentialDiagnosis>
      <TeachingPoint>Point1</TeachingPoint>
      <TeachingPoint>Point2</TeachingPoint>
   </newRecord>
   <newRecord>
      <Category>Category One</Category>
      <Subcategory>Subcategory</Subcategory>
      <Case>2</Case>
      <CaseTitle>Title Two</CaseTitle>
      <Institution>Title Two</Institution>
      <Author>Author Two</Author>
      <History>History Two</History>
      <DifferentialDiagnosis>Sick</DifferentialDiagnosis>
      <DifferentialDiagnosis>Sicker</DifferentialDiagnosis>
      <DifferentialDiagnosis>Sickest</DifferentialDiagnosis>
      <TeachingPoint>Point1</TeachingPoint>
      <TeachingPoint>Point2</TeachingPoint>
   </newRecord>
</data>

With help from the list, I am using this to get the results.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
    
    <xsl:output indent="yes" />
    
    <xsl:template match="Cases/Story">
        <data>
            <xsl:apply-templates select="Category[1]" />
        </data>
    </xsl:template>
    
    <xsl:template match="Category">
        <xsl:element name="newRecord">
            <Category><xsl:value-of select="substring-before(.,':
')"/></Category>
            <Subcategory><xsl:value-of select="substring-after(.,':
')"/></Subcategory>
            <Case><xsl:number count="Category"/></Case>
            <xsl:apply-templates
                select="following-sibling::*[1][not(self::Category)]"
mode="in-case-siblings"/>
        </xsl:element>
        <xsl:apply-templates select="following-sibling::Category[1]"/>
    </xsl:template>
    
    <xsl:template match="*" mode="in-case-siblings">
        <xsl:copy-of select="." />
        <xsl:apply-templates
            select="following-sibling::*[1][not(self::Category)]"
mode="in-case-siblings"/>
    </xsl:template>
    
    <xsl:template match="Category" mode="in-case-siblings"/>

</xsl:stylesheet>

This is working well, but now I need to do something different to the
<DifferentialDiagnosis> elements. I want to change the element names by
numbering them sequentially within my <newRecord> element, like this:

<?xml version="1.0" encoding="UTF-8"?>
<data>
   <newRecord>
      <Category>Category</Category>
      <Subcategory>Subcategory</Subcategory>
      <Case>1</Case>
      <CaseTitle>Title One</CaseTitle>
      <Institution>Institution One</Institution>
      <Author>Authors One</Author>
      <History>History One</History>
      <DifferentialDiagnosis1>Sick</DifferentialDiagnosis1>
      <DifferentialDiagnosis2>Sicker</DifferentialDiagnosis2>
      <DifferentialDiagnosis3>Sickest</DifferentialDiagnosis3>
      <TeachingPoint>Point1</TeachingPoint>
      <TeachingPoint>Point2</TeachingPoint>
   </newRecord>
   <newRecord>
      <Category>Category One</Category>
      <Subcategory>Subcategory</Subcategory>
      <Case>2</Case>
      <CaseTitle>Title Two</CaseTitle>
      <Institution>Title Two</Institution>
      <Author>Author Two</Author>
      <History>History Two</History>
      <DifferentialDiagnosis1>Sick</DifferentialDiagnosis1>
      <DifferentialDiagnosis2>Sicker</DifferentialDiagnosis2>
      <DifferentialDiagnosis3>Sickest</DifferentialDiagnosis3>
<TeachingPoint>Point1</TeachingPoint>
      <TeachingPoint>Point2</TeachingPoint>
   </newRecord>
</data>

I added this rule to my stylesheet:

    <xsl:template match="DifferentialDiagnosis" mode="in-case-siblings">
        <xsl:variable name="diagnosis"><xsl:number
count="DifferentialDiagnosis" from="Category"/></xsl:variable>
        <xsl:element name="{concat(name(),$diagnosis)}"><xsl:value-of
select="."/></xsl:element>
        <xsl:apply-templates
            select="following-sibling::*[1][not(self::Category)]"
mode="in-case-siblings"/>            
    </xsl:template>

This basically "works" except the numbers are sequential throughout the
document. 

<data>
   <newRecord>
	...
      <DifferentialDiagnosis1>Sick</DifferentialDiagnosis1>
      <DifferentialDiagnosis2>Sicker</DifferentialDiagnosis2>
      <DifferentialDiagnosis3>Sickest</DifferentialDiagnosis3>
	...
   </newRecord>
   <newRecord>
	...
      <DifferentialDiagnosis1>Sick</DifferentialDiagnosis5>
      <DifferentialDiagnosis2>Sicker</DifferentialDiagnosis6>
      <DifferentialDiagnosis3>Sickest</DifferentialDiagnosis7>
	...
   </newRecord>
</data>

I need the numbers to reset for each <newRecord> element. I am sorry for the
long post, but I want to be complete as possible. Also, for this project, I
need to use XSLT 1.0. Thank you very much.

Rick

Current Thread