Solved

XSLT: open tag on first condition, close tag on second.  Breaks XML'ishness of XSLT.

Posted on 2004-04-01
1
716 Views
Last Modified: 2010-05-18
So this has been a problem I have been kicking around for awhile.  I have actually given up on doing it in XSLT and just ripped it out with the DOM in code and then cache the resulting html string at the application scope.

Nevertheless:

Assume an xml structure like so.

<root>
  <item num="1" />
  <item num="2" />
  <item num="3" >
      <item num="1" />
      <item num="2" />
      <item num="3" />
  </item>
  <item num="4" />
  <item num="5" />
</root>

And then assume that the output that I would like should look like this:
<ul>
    <li>1</li>
    <li>2</li>
    <li>3
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
    </li>
    <li>4</li>
    <li>5</li>
</ul>

There is of course explicit ways of having the output be displayed in that manner.  But of course it isn't that simple.

1. You don't know the depth of the node structure ahead of time.  It can conceivably be as deep as it wants to be, meaning the output would have to create new unordered list elements for each node depth.

2. Well there really isn't a number 2.

Now me being the sharp guy that I am found that we can locate the beginning of a new node depth with the directive: count(preceding-sibling::*)=0

and we can know we are at the end of a node depth group with the directive: count(following-sibling::*)=0

So we can simply make a nice <xsl:choose> group with three statements, if we are at the start of a node depth area begin the template with a "<ul>".  Then if we are at the end of a node depth area then end the template with a "</ul>".  And the xsl:otherwise would just output a simple <li>.  Easy.

Well, easy in theory (at least in the theory of how I would LIKE it to work)..

Of course it does'nt work because it has mismatched tags that then break the xml'ishness (technical term) of the xslt.

This is a puzzler.

Does anyone have a solution?

Below is the broken xslt template.  note the open <ul> in the first <xsl:when> and the closing <ul> in the second when statement.  Removing those will make it operational.

<xsl:template match="item">                  
      <xsl:choose>
            <xsl:when test="count(preceding-sibling::*)=0">
                  <ul>
                        <li>
                        <xsl:value-of select="@num " />
                        </li>
                  <xsl:apply-templates select="item" />      
                                    
            </xsl:when>
                  
            <xsl:when test="count(following-sibling::*)=0">
                        <li>
                        <xsl:value-of select="@num " />
                        </li>
                        
                  </ul>
                  <xsl:apply-templates select="item" />      
                              
            </xsl:when>
                  
            <xsl:otherwise>
                  <li>
                        <xsl:value-of select="@num " />
                  </li>
                  <xsl:apply-templates select="item" />      
            </xsl:otherwise>            
                  
      </xsl:choose>      
</xsl:template>
0
Comment
Question by:gregoftheweb
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
1 Comment
 

Accepted Solution

by:
jurn earned 125 total points
ID: 10738179
how about something like..

<xsl:template match="root">
    <ul>
      <xsl:apply-templates/>
    </ul>
</xsl:template>
<xsl:template match="item">
    <li>
      <xsl:value-of select="@num"/>
      <xsl:if test="item">
        <ul>
          <xsl:apply-templates/>
        </ul>
      </xsl:if>
    </li>
</xsl:template>

hope it helps.
jurn
0

Featured Post

Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Learn by example how to specify CSS selectors for Selenium WebDriver test automation software.
Dramatic changes are revolutionizing how we build and use technology. Every company is automating, digitizing, and modernizing operations. We need a better, more connected way to work together as teams so we can harness the insights from our system…
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.
Learn how to create flexible layouts using relative units in CSS.  New relative units added in CSS3 include vw(viewports width), vh(viewports height), vmin(minimum of viewports height and width), and vmax (maximum of viewports height and width).

696 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question