tags:

views:

907

answers:

4

I have a xml build of

<elig>
 <subscriber code="1234"/>
    <date to="12/30/2004"
        from="12/31/2004"/>
       <person name="bob"
           ID="654321"/>
       <dog type="labrador"
            color="white"/>
    <location name="hawaii"
              islandCode="01"/>
 </subscriber>
</elig>

In XSL I have:

<xsl:template match="subscriber">
 <xsl:for-each select="date">
  <xsl:apply-templates match="person" />
  <xsl:apply-templates match="location" />
  <xsl:apply-templates match="dog" />
 </xsl:for-each>
</xsl:template>

The problem I have is that I need the location block in between the person and the dog block. I have tried ../ and it does not work. I simplified this majorly but the point comes across. I can't seem to remember what I need to place in front of location to get it to work. Thanks.

+1  A: 

I modified one typo in your example XML:

<elig>
 <subscriber code="1234">
    <date to="12/30/2004" from="12/31/2004"/>
       <person name="bob" ID="654321"/>
       <dog type="labrador" color="white"/>
    <location name="hawaii" islandCode="01"/>
 </subscriber>
</elig>

And using this stylesheet everything works just fine:

<xsl:template match="subscriber">
 <xsl:for-each select="date">
  <xsl:apply-templates select="../person" />
  <xsl:apply-templates select="../location" />
  <xsl:apply-templates select="../dog" />
 </xsl:for-each>
</xsl:template>

<xsl:template match="person">person</xsl:template>
<xsl:template match="location">location</xsl:template>
<xsl:template match="dog">dog</xsl:template>

Output is:

personlocationdog
mkoeller
+1  A: 

First of all your XML is still not well-formed and I actually cannot catch why you're looping over the <date/> tags - there is only one <date/> tag inside <subscriber/> (assuming that the first <subscriber/> should not be self-closed).

When using XPath you alway have to think about the context in which the XPatch is called. The following should do it (when my assumption about your data structure is correct):

<xsl:template match="subscriber">
 <xsl:for-each select="date"> 
  <!-- from here on we're in the context of the date-tag -->
  <xsl:apply-templates match="../person" />
  <xsl:apply-templates match="../location" />
  <xsl:apply-templates match="../dog" />
 </xsl:for-each>
</xsl:template>
Stefan Gehrig
I had a bunch of things wrong and once fixed the ../location worked, just one of those days .....
Primetime
A: 

In this case, isn't it more logical to move the apply-template calls outside the for-each loop? Since the person, location and dog elements are children of the subscriber, they should be processed within the scope of the subscriber, instead of in the scope of the date.

I.e.:

<xsl:template match="subscriber">
  <xsl:for-each select="date">
     <!-- Perform the processing of the date tags here-->
  </xsl:for-each>

  <xsl:apply-templates match="person" />
  <xsl:apply-templates match="location" />
  <xsl:apply-templates match="dog" />
</xsl:template>
Alderath
A: 
<xsl:template match="subscriber">
  <xsl:apply-templates match="date" />
</xsl:template>

<xsl:template match="date">
  <xsl:apply-templates match="../person" />
  <xsl:apply-templates match="../location" />
  <xsl:apply-templates match="../dog" />
</xsl:template>

      instead of xsl:for-each on date better practice is having a template match for date.
Laxmikanth Samudrala