Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

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

Posted on 2004-04-01
1
Medium Priority
?
732 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 500 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

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Today, the web development industry is booming, and many people consider it to be their vocation. The question you may be asking yourself is – how do I become a web developer?
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…
The viewer will learn how to dynamically set the form action using jQuery.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.
Suggested Courses

618 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