[Home] [By Thread] [By Date] [Recent Entries]
On 13.08.2020 19:15, Terry Ofner tdofner@xxxxxxxxx wrote:
I have a set of problems in the following format: <set> <p class="directions">Write <span class="letter">S</span> if <span class="term">sentence</span>; write <span class="letter">F</span> if <span class="term">fragment</span></p> <p class="nl">	1.	Sentence (or fragment) here.</p> <p class="nl">	2.	Another sentence/fragment here.</p> <p class="nl">	3.	Yet another.</p> </set> directions for each item and number the choices sequentially starting with zero:
three, others have more. Because of the variable number of choices, I decided to use grouping. For example, here is a section of the transform that produces a perfect set of <write_choice> elements for each item. The selected node is <p class="nl"> and a copy of <p class='directions'> is stored in <xsl:variable name="myDir" /> group-starting-with="span[@class='letter']"> select="current-group()[1][self::span[@class='letter']]"/><write_choice> <xsl:attribute name="letter"> <xsl:value-of </xsl:attribute> <xsl:attribute name="term"> <xsl:value-of select="current-group()[2][self::span[@class='term']]"/> </xsl:attribute> </write_choice> </xsl:for-each-group> </write_choices>
Then you can push the map for each of the p[@class = 'nl'] through a template creating a write_choice: <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"> <xsl:output indent="yes"/> <xsl:template match="set[p[@class = 'nl']]">
<xsl:variable name="groups" as="map(xs:string, element())*">
<xsl:for-each-group select="p[@class = 'directions']/*"
group-starting-with="span[@class = 'letter']">
<xsl:sequence select="map { 'letter' : ., 'term' :
current-group()[2] }"/>
</xsl:for-each-group>
</xsl:variable>
<write_choices>
<xsl:apply-templates select="p[@class = 'nl'] ! $groups"/>
</write_choices>
</xsl:template> <xsl:template match=".[. instance of map(xs:string, element())]">
<write_choice num="{position() - 1}" letter="{?letter}"
term="{?term}"/>
</xsl:template></xsl:stylesheet> I certainly see no need to nest for-each-group and iterate but you could of course use iterate instead of the apply-templates: <xsl:template match="set[p[@class = 'nl']]">
<xsl:variable name="groups" as="map(xs:string, element())*">
<xsl:for-each-group select="p[@class = 'directions']/*"
group-starting-with="span[@class = 'letter']">
<xsl:sequence select="map { 'letter' : ., 'term' :
current-group()[2] }"/>
</xsl:for-each-group>
</xsl:variable>
<write_choices>
<xsl:iterate select="p[@class = 'nl'] ! $groups">
<write_choice num="{position() - 1}" letter="{?letter}"
term="{?term}"/>
</xsl:iterate>
</write_choices>
</xsl:template>
|

Cart



