[xsl] nesting flat varaible structures?

Subject: [xsl] nesting flat varaible structures?
From: dvint@xxxxxxxxx
Date: Fri, 23 Sep 2011 12:25:19 -0700
I'm trying to use XSLT to do a conversion from one version of the S1000D
spec to another. So in the older version you can have this:

<reqpers>
<person man="1"/>
<perscat category="tech"/>
<trade>foo</trade>
<person man="2"/>
<perscat category="techa"/>
<perskill skill="sk05"/>
<trade>bar</trade>
<esttime>23</esttime>
</reqpers>

In the newer version you have a nested structure:

<reqPersons>
<person man="1">
  <personCategory personCategoryCode="tech"/>
  <trade>foo</trade>
</person>
<person man="2">
  <personCategory personCategoryCode="techa"/>
  <personSkill skillLevelCode="sk05"/>
  <trade>bar</trade>
  <esttime>23</esttime>
</person>
<reqPersons>

I can use the following sibling to pull the elements under a new <person>
tag, but the problem is that none of the following elements are requried.
So this will work if I have a consistent combination of elements.

<xsl:template match="person">
<person>
  <xsl:call-template name="processSecurityAttributes"/>
  <xsl:call-template name="processsChangeAttributes"/>
  <xsl:call-template name="processsIDAttributes"/>
  <xsl:call-template name="processsApplicabilityAttributes"/>
  <xsl:if test="@man">
    <xsl:attribute name="man" select="@man"/>
  </xsl:if>

<xsl:for-each select="following-sibling::perscat[1]">
<personCategory>
  <xsl:call-template name="processSecurityAttributes"/>
  <xsl:call-template name="processsChangeAttributes"/>
  <xsl:call-template name="processsIDAttributes"/>
  <xsl:call-template name="processsApplicabilityAttributes"/>
  <xsl:if test="@category">
     <xsl:attribute name="personCategoryCode" select="@category"/>
  </xsl:if>
</personCategory>
</xsl:for-each>

<xsl:for-each select="following-sibling::perskill[1]">
<personSkill>
   <xsl:call-template name="processSecurityAttributes"/>
   <xsl:call-template name="processsChangeAttributes"/>
   <xsl:call-template name="processsIDAttributes"/>
   <xsl:call-template name="processsApplicabilityAttributes"/>
   <xsl:if test="@skill">
     <xsl:attribute name="skillLevelCode" select="@skill"/>
   </xsl:if>
</personSkill>
</xsl:for-each>

<xsl:for-each select="following-sibling::trade[1]">
<trade>
   <xsl:call-template name="processSecurityAttributes"/>
   <xsl:call-template name="processsChangeAttributes"/>
   <xsl:call-template name="processsIDAttributes"/>
   <xsl:call-template name="processsApplicabilityAttributes"/>
</trade>
</xsl:for-each>

<xsl:for-each select="following-sibling::esttime[1]">
<estimatedTime unitOfMeasure="minutes">
  <xsl:call-template name="processSecurityAttributes"/>
  <xsl:call-template name="processsChangeAttributes"/>
  <xsl:call-template name="processsIDAttributes"/>
  <xsl:call-template name="processsApplicabilityAttributes"/>
  <xsl:apply-templates/>
</xsl:for-each>

</person>
</xsl:template>


I'm using the for-each to set context for the other templates and the
following-sibling::xx[1] to just make sure I pull the first one if there
is more than one match to the right.

This is producing the wrong output becasue in some cases the first
following sibling has an intervening person element:

<reqPersons>
   <person man="1">
      <personCategory personCategoryCode="tech"/>
      <personSkill skillLevelCode="sk05"/>
      <trade/>
      <estimatedTime unitOfMeasure="minutes">23</estimatedTime>
   </person>
   <person man="2">
      <personCategory personCategoryCode="techa"/>
      <personSkill skillLevelCode="sk05"/>
      <trade/>
      <estimatedTime unitOfMeasure="minutes">23</estimatedTime>
   </person>
</reqPersons>

I'm working in 2.0. Any ideas on how to correct the results?

..dan

Current Thread