hnmcc 0 Newbie Poster

I am very much a newbie with XSL, so apologies for that!

I'm modifying an XSL stylesheet, the purpose of which is to display as HTML output from a search engine. The inbound XML is repetitive: <response> is root, and it holds some header information; then there's a node called <return> which contains iterations of <doc>. The child nodes in <doc> are all in the form <str name="foo">: these are what I need to display.

XML

<?xml version="1.0" encoding="UTF-8"?>
<response>
	<lst name="responseHeader">
		<int name="status">0</int>
		...
	</lst>
	<result name="response" numFound="3" start="0">
		<doc>
			<str name="title">???</str>
			<str name="manu">???</str>
			<str name="name">???</str>
			<str name="subject">???</str>
		</doc>
		<doc>
		....
		</doc>
	</result>
</response>

It's essential that I can format the different child nodes in <doc> separately, according to their name value. That's to say, all those named "title" must be formatted the same as each other, all those named "manu" the same as each other, and so on.

The code I'm using doesn't allow this: the output from the child-nodes for each <doc> is grouped together (which is good) and formatted identically (NOT good).

The XSL code I'm using is as follows:

<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output media-type="text/html; charset=UTF-8" encoding="UTF-8"/>
	<xsl:variable name="title" select="concat('Search results - ',response/result/@numFound,' documents')"/>
	
	<xsl:template match="/">

		<html>
			<head>
				<title>
					<xsl:value-of select="$title"/>
				</title>
				<xsl:call-template name="css"/>
			</head>
			<body>
				<div id="page">
					<h1>
						<xsl:value-of select="$title"/>
					</h1>
					<xsl:apply-templates select="response/result/doc"/>
				</div>
			</body>
		</html>
	
	</xsl:template>


	<xsl:template match="doc">
		<xsl:variable name="pos" select="position()"/>
		<div class="item">
			<div class="inner">
				<xsl:apply-templates>
					<xsl:with-param name="pos">
						<xsl:value-of select="$pos"/>
					</xsl:with-param>
				</xsl:apply-templates>
			</div>
		</div>
	</xsl:template>
	
	
	<xsl:template match="doc/*[@name='score']" priority="100">
		<xsl:param name="pos"/>
		<tr>
			<td class="name">
				<xsl:value-of select="@name"/>
			</td>
			<td class="value">
				<xsl:value-of select="."/>
				<xsl:if test="boolean(//lst[@name='explain'])">
					<xsl:element name="a">
						<!-- can't allow whitespace here -->
						<xsl:attribute name="href">javascript:toggle("<xsl:value-of select="concat('exp-',$pos)"/>");</xsl:attribute>?</xsl:element>
					<br/>
					<xsl:element name="div">
						<xsl:attribute name="class">exp</xsl:attribute>
						<xsl:attribute name="id">
							<xsl:value-of select="concat('exp-',$pos)"/>
						</xsl:attribute>
						<xsl:value-of select="//lst[@name='explain']/str[position()=$pos]"/>
					</xsl:element>
				</xsl:if>
			</td>
		</tr>
	</xsl:template>
	

	<xsl:template match="doc/arr" priority="100">
    <tr>
      <td class="name">
        <xsl:value-of select="@name"/>
      </td>
      <td class="value">
        <ul>
        <xsl:for-each select="*">
          <li><xsl:value-of select="."/></li>
        </xsl:for-each>
        </ul>
      </td>
    </tr>
  </xsl:template>
	<!--<xsl:template match="doc/*">-->
	<xsl:template match="response/result/doc/str">
		<!--<tr>-->
		<!--<td class="name">
        <xsl:value-of select="@name"/>
      </td>-->
		<!--<td class="value">
        <xsl:value-of select="."/>
      </td>-->
		<!--<xsl:variable name="heading" select="@title" />-->
		<div class="inner">
			<!--<div class="<xsl:value-of select="position()"/>">-->
				<xsl:value-of select="."/>
			<!--</div>-->
		</div>
		<!--</tr>-->
	</xsl:template>


	<xsl:template match="*"/>


	<xsl:template name="css">
		<script>
      function toggle(id) {
        var obj = document.getElementById(id);
        obj.style.display = (obj.style.display != 'block') ? 'block' : 'none';
      }
    </script>
		<style type="text/css">
            body {font-family:Arial,"Microsoft Sans Serif",Tahoma,"Nimbus Sans L",Helvetica,sans-serif;}
      		#page{margin:0 5% 0 5%;font-size:80%;}
			h1{color:00487d;font-weight:normal;font-size:300%;}
			.item{margin-top:1em;padding:1em;border:solid #0066b3 1px;background:#bfe4ff;}
			.inner{padding:1em;background:#fff;line-height:150%;-moz-column-count:2;}
    </style>
	</xsl:template>


</xsl:stylesheet>

For my output, I would prefer to place the content of each child-node into a <div>, using that node's position() value as the class name of the <div> containing the node's content. The code of the output would look like this:

<div class="doc">
	<div class="n">
		Blah blah blah.
	</div>
	<div class="n+1">
		Yawn!
	</div>
	...
</div>
<div class="doc">
...

- where "n" is the position() value for the child-node containing "Blah blah blah.", and "n+1"
 is the position() value for the child-node containing "Yawn!", and so on.

But I don't know how to achieve this, and every attempt I've made so far has produced invalid XSL.

Can anyone help me?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of 1.18 million developers, IT pros, digital marketers, and technology enthusiasts learning and sharing knowledge.