xsl:for-each-group not working as per exception - xslt

I have to transform XML tag out of p as separate div but i am unable to do it:
XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<p>
This is <bold>First</bold> paragraph
<boxed-text>
<sec>
<title>Boxed title</title>
<p>
<list list-type="bullet">
<list-item>
<p>List first para</p>
</list-item>
</list>
</p>
</sec>
</boxed-text>
This is <bold>Second</bold> paragraph
</p>
</root>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="xhtml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<html>
<head>
<title>Title</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="p">
<xsl:choose>
<xsl:when test="descendant::boxed-text">
<xsl:for-each-group select="node()" group-starting-with="node()">
<xsl:choose>
<xsl:when test="self::boxed-text">
<div class="boxed-text">
<xsl:apply-templates select="current-group()"/>
</div>
</xsl:when>
<xsl:otherwise>
<p class="indent">
<xsl:apply-templates select="current-group()"/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:when>
<xsl:otherwise>
<p class="indent">
<xsl:apply-templates/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="boxed-text">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="p[table-wrap | list]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="list">
<xsl:choose>
<xsl:when test="#list-type[. = 'bullet']">
<ol style="list-style-type:disc;">
<xsl:apply-templates/>
</ol>
</xsl:when>
<xsl:otherwise>
<ol style="list-style-type:none;">
<xsl:apply-templates/>
</ol>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="list-item">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
</xsl:stylesheet>
Current Output:
<?xml version="1.0" encoding="UTF-8"?><html>
<head>
<title>Title</title>
</head>
<body>
<p class="indent">
This is
</p>
<p class="indent">First</p>
<p class="indent"> paragraph
</p>
<div class="boxed-text">Boxed title
<ol style="list-style-type:disc;">
<li>
<p class="indent">List first para</p>
</li>
</ol>
</div>
<p class="indent">
This is
</p>
<p class="indent">Second</p>
<p class="indent"> paragraph
</p>
</body>
</html>
Excepted output:
<?xml version="1.0" encoding="UTF-8"?><html>
<head>
<title>Title</title>
</head>
<body>
<p class="indent">This is <b>First</b> paragraph</p>
<div class="boxed-text">Boxed title
<ol style="list-style-type:disc;">
<li>
<p class="indent">List first para</p>
</li>
</ol>
</div>
<p class="indent">This is <b>Second</b> paragraph</p>
</body>
</html>

It seems this is rather a job for group-adjacent="boolean(self::boxed-text)":
<xsl:template match="p[descendant::boxed-text]">
<xsl:for-each-group select="node()" group-adjacent="boolean(self::boxed-text)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<p class="indent">
<xsl:apply-templates select="current-group()"/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
Complete adaption is
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="html" indent="no" html-version="5"/>
<xsl:template match="/">
<html>
<head>
<title>.NET XSLT Fiddle Example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="p">
<p class="indent">
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="p[descendant::boxed-text]">
<xsl:for-each-group select="node()" group-adjacent="boolean(self::boxed-text)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<p class="indent">
<xsl:apply-templates select="current-group()"/>
</p>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="boxed-text">
<div class="boxed-text">
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="p[table-wrap | list]">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="list">
<ol style="list-style-type:none;">
<xsl:apply-templates/>
</ol>
</xsl:template>
<xsl:template match="list[#list-type[. = 'bullet']]">
<ol style="list-style-type:disc;">
<xsl:apply-templates/>
</ol>
</xsl:template>
<xsl:template match="list-item">
<li>
<xsl:apply-templates/>
</li>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/6rewNyg

Related

How does parent tag Attributes in the "apply templete" when it is in "group by"

Here is the Sample XML which I am using
XML.xml
<root>
<main>
<docum year="2022" month="2022.01">1</docum>
<docum year="2021" month="2021.12">2</docum>
<docum year="2020" month="2020.11">3</docum>
<docum year="2020" month="2020.12">4</docum>
<docum year="2022" month="2022.12">5</docum>
</main>
</root>
Need a navigator HTML which is toc.htm and 1.htm, 2.htm, 3.htm
toc.htm
<div>
<div>2022_2022.01</div>
<div>2022_2022.12</div>
<div>2022_2020.11</div>
</div>
1.htm
<div>
<h1>2022</h1>
<h2>2022.01</h2>
1
</div>
<div>
<h1>2022</h1>
<h2>2022.12</h2>
5
</div>
2.htm
<div>
<h1>2021</h1>
<h2>2021.12</h2>
2
</div>
3.htm
<div>
<h1>2020</h1>
<h2>2020.11</h2>
3
</div>
<div>
<h1>2020</h1>
<h2>2020.11</h2>
4
</div>
this is my XSL which I am trying but not sure about how we get parent div attributes value in the apply template in the current group().
XSL.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:template match="root">
<xsl:apply-templates select="main" mode="toc" />
<xsl:apply-templates select="main" mode="chapter" />
</xsl:template>
<xsl:template match="root/main" mode="toc">
<xsl:result-document href="toc.htm" method="html">
<html>
<body>
<xsl:for-each select="docum">
<xsl:element name="div">
<xsl:attribute name="class"></xsl:attribute>
<xsl:attribute name="id">
<xsl:value-of select="#year" />
</xsl:attribute>
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="lower-case(concat('id_', generate-id(), '.htm'))" />
</xsl:attribute>
<xsl:value-of select="#year" /> _<xsl:value-of select="#month" />
</xsl:element>
</xsl:element>
</xsl:for-each>
</body>
</html>
</xsl:result-document>
</xsl:template>
<xsl:template match="root/main" mode="chapter">
<xsl:for-each-group select="docum" group-by="#month">
<xsl:result-document href="{lower-case(concat('id_', generate-id()))}.htm" method="HTML">
<html>
<body>
<h1><xsl:value-of select="#year" /></h1>
<h2><xsl:value-of select="#month" /></h2>
<xsl:apply-templates select="current-group()" />
</body>
</html>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
I think you want something along the following lines:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:template match="root/main">
<xsl:result-document href="toc.html">
<html>
<head>
<title>TOC</title>
</head>
<body>
<xsl:for-each-group select="docum" group-by="#year">
<div id="g-{current-grouping-key()}">
{let $sorted-months := sort(current-group()/#month, (), function($m) { $m }) return $sorted-months[1] || ('-' || $sorted-months[last()])[$sorted-months[2]]}
</div>
<xsl:result-document href="year-{current-grouping-key()}.html">
<html>
<head>
<title>{current-grouping-key()}</title>
</head>
<body>
<xsl:apply-templates select="current-group()"/>
</body>
</html>
</xsl:result-document>
</xsl:for-each-group>
</body>
</html>
</xsl:result-document>
</xsl:template>
<xsl:template match="docum">
<div>
<h1>{#year}</h1>
<h2>{#month}</h2>
{.}
</div>
</xsl:template>
</xsl:stylesheet>
This creates toc.html and for each year a year-yyyy.html which I think then has the contents you want, i.e. each month belonging to that year.

How do I add .01 to the end of a number using XSLT?

I need to add .01 to the entry in this line of code in my XSLT script <xsl:apply-templates select="descendant::xhtml:span[#property = 'atom:content-item-name']"/>. This number appears twice in my output. I only need the .01 on the second entry. How would I do that? I guess it would be in effect a counter because if there are 2 questions I'd need it to number as .02, etc.
This is the full XSLT script:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://exslt.org/math"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:mml="http://www.w3.org/1998/Math/MathML"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="xs math xd xhtml mml"
version="3.0">
<xsl:output encoding="UTF-8" include-content-type="no" indent="no" method="xhtml" omit-xml-declaration="yes"/>
<!-- attributes, commments, processing instructions, text: copy as is -->
<xsl:template match="#*|comment()|processing-instruction()|text()">
<xsl:copy-of select="."/>
</xsl:template>
<!-- elements: create a new element with the same name, but no namespace -->
<xsl:template match="*">
<xsl:param name="content-item-name"/>
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*|node()">
<xsl:with-param name="content-item-name" select="$content-item-name"/>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<!-- process root -->
<xsl:template match="xhtml:html">
<xsl:text disable-output-escaping="yes"><!DOCTYPE html></xsl:text>
<xsl:sequence select="'
'"/>
<html>
<xsl:apply-templates select="#* | node()"/>
</html>
</xsl:template>
<!-- process item, pass content item name variable -->
<xsl:template match="xhtml:li[#property='ktp:question']">
<li>
<xsl:apply-templates select="#*|node()">
<xsl:with-param name="content-item-name" select="descendant::xhtml:span[#property='atom:content-item-name']/#data-value"/>
</xsl:apply-templates>
</li>
</xsl:template>
<!-- branching point for any interaction type-based updates -->
<xsl:template match="xhtml:li[#property='ktp:question']">
<li>
<xsl:apply-templates select="#*|node()">
<xsl:with-param name="interactionType" select="//xhtml:span[#property='ktp:interactionType']"/>
</xsl:apply-templates>
</li>
</xsl:template>
<!-- Change content -->
<xsl:template match="xhtml:ol[#class='ktp-question-set']">
<xsl:variable name="content-item-name" select="xhtml:span[#property='atom:content-item-name']/#data-value"/>
<xsl:variable name="feedbackPara"
select="xhtml:section[#property = 'ktp:stimulus']"/>
<ol property="ktp:questionSet" typeof="ktp:QuestionSet" class="ktp-question-set">
<li class="ktp-question-set-meta">
<section property="ktp:metadata" class="ktp-meta">
<xsl:apply-templates
select="descendant::xhtml:span[#property = 'atom:content-item-name']"/>
</section>
<section property="ktp:tags" class="ktp-meta">
<span class="ktp-meta" property="ktp:questionSetType">shared-stimulus</span>
</section>
</li>
<li class="ktp-stimulus" typeof="ktp:Stimulus" property="ktp:stimulus">
<xsl:apply-templates
select="descendant::xhtml:section[#property = 'ktp:stimulus']"/>
<p class="place-top atom-exclude">Stimulus End: Place content above this line</p>
</li>
<li class="ktp-question" typeof="ktp:Question" property="ktp:question">
<section class="ktp-question-meta">
<section property="ktp:metadata" class="ktp-meta">
<xsl:apply-templates
select="descendant::xhtml:span[#property = 'atom:content-item-name']"/>
</section>
<xsl:apply-templates
select="descendant::xhtml:section[#property = 'ktp:tags']"/>
</section>
<xsl:apply-templates
select="descendant::xhtml:section[#class = 'ktp-question-stem']"/>
<xsl:apply-templates
select="descendant::xhtml:ol[#class = 'ktp-answer-set']"/>
<xsl:apply-templates
select="descendant::xhtml:section[#property = 'ktp:explanation']"/>
</li>
</ol>
</xsl:template>
</xsl:stylesheet>
This is the input section where I need to pull the data-value from:
<section class="ktp-question-meta">
<section property="ktp:metadata" class="ktp-meta"><span property="atom:content-item-name" class="ktp-meta" data-value="lsac820402"></span></section>
<section property="ktp:tags" class="ktp-meta">
<span property="ktp:interactionType" class="ktp-meta">single-select</span>
<span property="ktp:questionType" class="ktp-meta">Assumption (Sufficient)</span>
<span property="ktp:difficulty" class="ktp-meta">★</span>
</section>
This is how I need that section to appear with the .01 added to that data-value:
<section class="ktp-question-meta">
<section property="ktp:metadata" class="ktp-meta">
<span property="atom:content-item-name" class="ktp-meta" data-value="lsac820402.01"></span>
</section>

XSLT passing variables inside nested for-each loops

I am fairly new at this and I am not sure if it is possible to do what I want to achieve here. I have 3 for-each loops that stores a number for every chapter, section and paragraph. I want to get that stored number from the previous for-each loop and display it in the nested loop, but I can't get it to work.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title>Table of Contents, Chapter 3</title>
</head>
<body>
<xsl:for-each select="chapter">
<tr>
<xsl:variable name="capnr">
<xsl:number value="3" format="1. "/>
</xsl:variable>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="#title"/>
</tr>
<br />
<xsl:for-each select="section">
<tr>
<xsl:variable name="secnr">
<xsl:number format="1. "/>
</xsl:variable>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="$secnr"/>
<xsl:value-of select="#title"/>
</tr>
<br />
<xsl:for-each select="paragraph">
<tr>
<xsl:variable name="parnr">
<xsl:number format="1 "/>
</xsl:variable>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="$secnr"/>
<xsl:value-of select="$parnr"/>
<xsl:value-of select="#title"/>
</tr>
</xsl:for-each>
<br />
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
XML:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="ToC-3.xsl"?>
<chapter title="Chapter 3: Expressions">
<section title="Variables">
<paragraph title="Simple variables"></paragraph>
<paragraph title="Text variables"></paragraph>
<paragraph title="Remote identifiers"></paragraph>
</section>
<section title="The logical operators">
<paragraph title="Precedence of Boolean operators"></paragraph>
</section>
<section title="Designational expressions">
</section>
</chapter>
Without more details on the input and output, this should work. Of note is that the variable name is on the root, to allow all templates to access it. but since there appears to be one XSl per chapter this shouldn't be a problem.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="capnr">
<xsl:number value="3" format="1."/>
</xsl:variable>
<xsl:template match="/">
<html>
<head>
<title>Table of Contents, Chapter 3</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="chapter">
<h1>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="#title"/>
</h1>
<ol><xsl:apply-templates/></ol>
</xsl:template>
<xsl:template match="section">
<li>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="position()"/>
<xsl:text> - </xsl:text>
<xsl:value-of select="#title"/>
<ol><xsl:apply-templates/></ol>
</li>
</xsl:template>
<xsl:template match="paragraph">
<li>
<xsl:value-of select="$capnr"/>
<xsl:value-of select="count(../preceding-sibling::*) + 1"/>
<xsl:text>.</xsl:text>
<xsl:value-of select="position()"/>
<xsl:text> - </xsl:text>
<xsl:value-of select="#title"/>
<ol><xsl:apply-templates/></ol>
</li>
</xsl:template>
</xsl:stylesheet>
The above when applied to the given input XMl gives:
<html>
<head>
<title>Table of Contents, Chapter 3</title>
</head>
<body>
<h1>3.Chapter 3: Expressions</h1>
<ol><li>3.1 - Variables<ol><li>3.1.1 - Simple variables<ol></ol>
</li>
<li>3.1.2 - Text variables<ol></ol>
</li>
<li>3.1.3 - Remote identifiers<ol></ol>
</li>
</ol>
</li>
<li>3.2 - The logical operators<ol><li>3.2.1 - Precedence of Boolean operators<ol></ol>
</li>
</ol>
</li>
<li>3.3 - Designational expressions<ol></ol>
</li>
</ol>
</body>
</html>

How can i output this html with xsl( I want to exit an element)

I have this xsl bellow :
<xsl:template match="/" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns:d="http://schemas.microsoft.com/sharepoint/dsp" xmlns:asp="http://schemas.microsoft.com/ASPNET/20" xmlns:__designer="http://schemas.microsoft.com/WebParts/v2/DataView/designer" xmlns:SharePoint="Microsoft.SharePoint.WebControls">
<div id="vtab">
<ul>
<xsl:call-template name="dvt_1.body"/>
</ul>
</div>
</xsl:template>
<xsl:template name="dvt_1.body">
<xsl:for-each select="/dsQueryResponse/Rows/Row[generate-id(.)=generate-id(key('TitleKey', #Title))]">
<li>
<xsl:value-of select="#Title"/>
</li>
<xsl:variable name="thisClassification" select="#Title" />
<div>
<xsl:for-each select="../Row[#Title = $thisClassification]">
<xsl:value-of select="#Model"/>
</xsl:for-each>
</div>
</xsl:for-each>
</xsl:template>
I would like have this output:
<div id="vtab">
<ul>
<li>HTC</li>
<li>Nokia</li>
</ul>
<div>HTC Sensation 345-HTC Ev</div>
<div>Nokia</div>
</div>
But now this is what i'm getting
<div id="vtab">
<ul>
<li>HTC</li>
<div>HTC Sensation 345HTC Evo</div>
<li>Nokia</li>
<div>Nokia</div>
</ul>
</div>
How can i exit the UL element and start the DIV element.
Thanks alot
It is not optimal, but consider making two loops something like the following:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<div id="vtab">
<xsl:call-template name="LOOP_1"/>
<xsl:call-template name="LOOP_2"/>
</div>
</xsl:template>
<xsl:template name="LOOP_1">
<ul>
<xsl:for-each select="/dsQueryResponse/Rows/Row[generate-id(.)=generate-id(key('TitleKey', #Title))]">
<li>
<xsl:value-of select="#Title"/>
</li>
<xsl:variable name="thisClassification" select="#Title"/>
<div>
<xsl:for-each select="../Row[#Title = $thisClassification]">
<xsl:value-of select="#Model"/>
</xsl:for-each>
</div>
</xsl:for-each>
</ul>
</xsl:template>
<xsl:template name="LOOP_2">
<div>
<xsl:for-each select="/dsQueryResponse/Rows/Row[generate-id(.)=generate-id(key('TitleKey', #Title))]">
<xsl:variable name="thisClassification" select="#Title"/>
<div>
<xsl:for-each select="../Row[#Title = $thisClassification]">
<xsl:value-of select="#Model"/>
</xsl:for-each>
</div>
</xsl:for-each>
</div>
</xsl:template>
</xsl:stylesheet>
I am not sure of your requirements, but it may be more efficient to review the desired output, and output nested lists and format it using CSS rather than creating separate loops

XSLT increment variable

I have the following XML
<data>
<records>
<record name="A record">
<info>A1</info>
<info>A2</info>
</record>
<record name="B record"/>
<record name="C record">
<info>C1</info>
</record>
</records>
</data>
how can I transform into following output, the problem is how can I count between on record, and record/info?
<div id="1">
<p>A record</p>
<span id="1">A1</span>
<span id="2">A2</span>
</div>
<div id="2">
<p>C record</p>
<span id="3">C1</span>
</div>
Solution 1. Fine grained traversal. This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="records">
<xsl:apply-templates select="*[1]"/>
</xsl:template>
<xsl:template match="record"/>
<xsl:template match="record[node()]">
<xsl:param name="pRecordNum" select="1"/>
<xsl:param name="pInfoNum" select="1"/>
<div id="{$pRecordNum}">
<xsl:apply-templates select="#*|*[1]">
<xsl:with-param name="pInfoNum" select="$pInfoNum"/>
</xsl:apply-templates>
</div>
<xsl:apply-templates select="following-sibling::record[node()][1]">
<xsl:with-param name="pRecordNum" select="$pRecordNum +1"/>
<xsl:with-param name="pInfoNum" select="$pInfoNum + count(info)"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="info">
<xsl:param name="pInfoNum"/>
<span id="{$pInfoNum}">
<xsl:value-of select="."/>
</span>
<xsl:apply-templates select="following-sibling::info[1]">
<xsl:with-param name="pInfoNum" select="$pInfoNum +1"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="#name">
<p>
<xsl:value-of select="."/>
</p>
</xsl:template>
</xsl:stylesheet>
Output:
<div id="1">
<p>A record</p>
<span id="1">A1</span>
<span id="2">A2</span>
</div>
<div id="2">
<p>C record</p>
<span id="3">C1</span>
</div>
Solution 2: preceding axe. This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="record"/>
<xsl:template match="record[node()]">
<div id="{count(preceding-sibling::record[node()])+1}">
<xsl:apply-templates select="#*|*"/>
</div>
</xsl:template>
<xsl:template match="info">
<span id="{count(preceding::info)+1}">
<xsl:value-of select="."/>
</span>
</xsl:template>
<xsl:template match="#name">
<p>
<xsl:value-of select="."/>
</p>
</xsl:template>
</xsl:stylesheet>
Solution 3: With fn:position() and preceding axe. This stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="records">
<xsl:apply-templates select="record[node()]"/>
</xsl:template>
<xsl:template match="record">
<div id="{position()}">
<xsl:apply-templates select="#*"/>
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="info">
<span id="{count(preceding::info)+1}">
<xsl:value-of select="."/>
</span>
</xsl:template>
<xsl:template match="#name">
<p>
<xsl:value-of select="."/>
</p>
</xsl:template>
</xsl:stylesheet>
Note: You need a explict pull style.
Edit: Missed any level numbering for span/#id.
There is a short way to do this in XSLT. Use the <xsl:number> instruction:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="record[info]">
<xsl:variable name="vPos">
<xsl:number count="record[info]"/>
</xsl:variable>
<div id="{$vPos}">
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="info">
<xsl:variable name="vPos">
<xsl:number from="/" level="any" count="info" />
</xsl:variable>
<span id="{$vPos}"><xsl:apply-templates/></span>
</xsl:template>
<xsl:template match="record[not(info)]"/>
</xsl:stylesheet>
When this transformation is applied on the provided XML document:
<data>
<records>
<record name="A record">
<info>A1</info>
<info>A2</info>
</record>
<record name="B record"/>
<record name="C record">
<info>C1</info>
</record>
</records>
</data>
the wanted, correct result is produced:
<data>
<records>
<div id="1">
<span id="1">A1</span>
<span id="2">A2</span>
</div>
<div id="2">
<span id="3">C1</span>
</div>
</records>
</data>