Reputation: 1733
i have a simple problem i cannot solve. I have the following xml and xsl. I need to print out the SPAN and P tag including their content when they are not inside a "title" tag. In this case i just want to print out their content. This is an extract of my code. Right now i always print out both tag and content and cannot achieve what i want. This is what i'm printing:
<?xml version="1.0" encoding="utf-8"?>
<article class="story-ipad sortir">
<title>
<p>Il était une fois
<span>à jamais</span>
</p>
<title>
<text>
<p>Resequam, necullitae exerio quis por si dolecature et mincta pro. <br/>
</p>
<span>La Belle et la Bête,</span>
</text>
</article>
And this is what i would like:
<?xml version="1.0" encoding="utf-8"?>
<article class="story-ipad sortir">
<title>
Il était une fois à jamais
</title>
<text>
<p>Resequam, necullitae exerio quis por si dolecature et mincta pro. <br/>
</p>
<span>La Belle et la Bête,</span>
</tex
t>
I cannot modify the code too much, what i want to do is in my last template that match many html tag add an exception to have different if the tag is analyzing is //title/span ecc....otherwise to have another templat i call just from within "tiltle" but only for span and p tags, cause all other tags must behave differently.Can you help me?
<xsl:template match="span|div|font|
tt|i|b|big|small|u|s|strike|
em|strong|q|sub|sup|cite|abbr|acronym|
hr|blockquote|center|
img|
table|col|colgroup|thead|tfoot|tbody|tr|p|
th|td|summary" name="html-noclass-t">
A CONDITION HERE TO FIND OUT IF THE TAG IS UNDER A CERTAIN PATH FOR EXAMPLE
<?xml version="1.0" encoding="utf-8"?>
<doc xml:lang="fr">
<article>
<titles id="U1402860665587eXC">
<title id="U1402864848468jy">
<p id="U1402864848468C8D">Il était une fois <br/>
<span id="U1402864848468aP">à jamais</span>
</p>
</br>
</title>
</titles>
<texte id="U14028606655875nG">
<p>Resequam, necullitae exerio quis por si dolecature et mincta pro. <br/>
</p>
<span id="U1402864848468liD">La Belle et la Bête,</span>
</texte>
</article>
</doc>
With an XSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="no"/>
<xsl:template match="/">
<xsl:apply-templates select="/doc/article" />
</xsl:template>
<xsl:template match="/doc/article">
<article class="story-ipad sortir">
<xsl:call-template name="header"/>
<xsl:call-template name="text"/>
</article>
</xsl:template>
<xsl:template name="header">
<xsl:choose>
<xsl:when test="//article/titles/title">
<xsl:apply-templates select="//article/titles/title"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<xsl:template name="text">
<xsl:choose>
<xsl:when test="//text">
<xsl:apply-templates select="//text"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<xsl:template match="span|div|font|
tt|i|b|big|small|u|s|strike|
em|strong|q|sub|sup|cite|abbr|acronym|
hr|blockquote|center|
img|
table|col|colgroup|thead|tfoot|tbody|tr|p|
th|td|summary" name="html-noclass-t">
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Views: 240
Reputation: 15391
I'm wondering whether you're overcomplicating things. If you want a <title>
element with text-only content, then write the title element and copy the text content directly without calling or applying templates. If you want special behavior for some descendants of a <title>
element, than you could write different templates with different matches, e.g. like so:
I'd suggest trying whether something like this does what you want to do:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates select="/doc/article" />
</xsl:template>
<xsl:template match="/doc/article">
<article class="story-ipad sortir">
<title>
<xsl:apply-templates select="titles/title"/>
</title>
<text>
<xsl:apply-templates select="texte/*"/>
</text>
</article>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="title//*[self::p or self::span or self::br]">
<xsl:apply-templates select="node()"/>
</xsl:template>
</xsl:stylesheet>
When applied to your source document (which I modified because it has a closing </br>
without a matching opening one):
<?xml version="1.0" encoding="utf-8"?>
<article class="story-ipad sortir">
<title>Il était une fois à jamais</title>
<text>
<p>Resequam, necullitae exerio quis por si dolecature et mincta pro. <br/>
</p>
<span>La Belle et la Bête,</span>
</text>
</article>
This comes out:
<?xml version="1.0" encoding="utf-8"?>
<article class="story-ipad sortir">
<title>
<title>
Il était une fois
à jamais
</title>
</title>
<text>
<p>Resequam, necullitae exerio quis por si dolecature et mincta pro. <br/>
</p>
<span>La Belle et la Bête,</span>
</text>
</article>
There's another thing I noticed: You're using structures like
<xsl:choose>
<xsl:when test="//article/titles/title">
<xsl:apply-templates select="//article/titles/title"/>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
This is equivalent to this one line:
<xsl:apply-templates select="//article/titles/title"/>
The empty <xsl:otherwise>
can be omitted in any case, which leaves you with a single case. When testing for a single case, <xsl:if>
is nicer. But in general, <xsl:if>
and <xsl:choose>
are over-used because in many cases, <xsl:apply-templates>
will do the job and is considered better practice in XSLT.
What you do is redundant double checking: You first check "is there something to supply to <xsl:apply-templates>
?", and if there is nothing to supply, you do nothing. However, when supplied with nothing, <xsl:apply-templates>
will do nothing anyways. So, no checking required. If there are no titles, <xsl:apply-templates>
won't do anything, and if there are titles, you'd be calling it anyways.
Upvotes: 2