问题
I have the following tokenizing template implemented in my XSLT.
<xsl:template match="sporting_arena/text()[normalize-space()]" name="split">
<xsl:param name="pText" select="."/>
<xsl:if test="normalize-space($pText)">
<li>
<xsl:call-template name="replace">
<xsl:with-param name="pText" select="substring-before(concat($pText, ';'), ';')"/>
</xsl:call-template>
</li>
<xsl:call-template name="split">
<xsl:with-param name="pText" select="substring-after($pText, ';')"/>
</xsl:call-template>
</xsl:if>
<xsl:template name="replace">
<xsl:param name="pText"/>
<xsl:if test="normalize-space($pText)">
<xsl:value-of select="substring-before(concat($pText, '*'),'*')"/>
<xsl:if test="contains($pText, '*')">
<br/>
<xsl:call-template name="replace">
<xsl:with-param name="pText" select="substring-after($pText, '*')"/>
</xsl:call-template>
</xsl:if>
</xsl:if>
</xsl:template>
I'm wondering if it is possible to add to this tokenizing system the ability to bold or italicize certain words in my XML element text using the same delimiter approach with a delimiter on each side of a word to indicate either bold or italicized.
XML Example with current system:
<sporting_arena>
Adelaide Oval: An awesome new bike and truck that drove up* a hill and never came back.;
The delimiter I choose here * places this text on a new line and now I'm;
On a new dot point.
</sporting_arena>
回答1:
"I'm wondering if it is possible to add to this tokenizing system the ability to bold or italicize certain words in my XML element text using the same delimiter approach with a delimiter on each side of a word to indicate either bold or italicized."
Yes, it is possible. And at this point you should be able to implement this yourself, using the same principle as the one utilized by the tokenizing template (which you call "split"). Creating a token tagged as <li>
is no different from creating one tagged <b>
or <i>
.
Edit:
In response to:
"I think there is a difference: while partitioning the text into
li
elements, every fragment of text eventually ends up inside a list item, and the delimiter;
marks where a list item should end and another immediately start. Conversely, the bold or italic markup would apply only to a text portion between a starting and an ending delimiter."
The required change is rather trivial. Consider the following example:
<xsl:template name="italic">
<xsl:param name="text"/>
<xsl:param name="delimiter" select="'*'"/>
<xsl:choose>
<xsl:when test="contains($text, $delimiter) and contains(substring-after($text, $delimiter), $delimiter)">
<xsl:value-of select="substring-before($text, $delimiter)"/>
<i>
<xsl:value-of select="substring-before(substring-after($text, $delimiter), $delimiter)"/>
</i>
<!-- recursive call -->
<xsl:call-template name="italic">
<xsl:with-param name="text" select="substring-after(substring-after($text, $delimiter), $delimiter)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
When this template is called as:
<p>
<xsl:call-template name="italic">
<xsl:with-param name="text" select="input"/>
</xsl:call-template>
</p>
with the input being:
<input>Lorem ipsum *dolor* sit amet, *consectetuer* adipiscing * elit.</input>
the result will be:
<p>Lorem ipsum <i>dolor</i> sit amet, <i>consectetuer</i> adipiscing * elit.</p>
Note that the last, odd delimiter is passed to the output as is.
You could generalize this template to handle other types of markup (e.g. bold) by parametrizing the name of the token element to create.
--
P.S. This solution proudly uses xsl:choose
. xsl:choose
is an integral part of the XSLT language, and there is absolutely nothing wrong with using it to its full advantage. It adds clarity to the code, while artificial attempts to avoid using it only end up obfuscating the code unnecessarily.
来源:https://stackoverflow.com/questions/29524975/xslt-tokenizing-template-to-italicize-and-bold-xml-element-text