XSLT: templates without mode ignored in result-documents - xslt

I'm learning to use the mode attribute and must being doing something wrong. Apologies if this has been answered before but I'm not finding it here.
I want to process "title" elements separately depending on their context. For the main document, I want to add an "a" element inside of it:
<xsl:template match="title">
<div>
<xsl:value-of select="."/>
<a href="some_URL">some text
</a>
</div>
</xsl:template>
But elsewhere I'm creating result-documents where I just want the title:
<xsl:tamplate match="title" mode="print">
<div class="title">
<xsl:value-of select="."/>
</div>
</xsl:template>
In my main template match="/" I'm doing a for-each for each section, creating a result-document for each one:
<xsl:for-each select="/topic/body/bodydiv/section">
<xsl:result-document href="{$printoutfile}">
<html><head>some stuff</head><body>
<div class="section">
<xsl:apply-templates mode="print"/>
</div>
... more stuff...
</body</html>
</xsl:result-document>
</xsl:for-each>
Then I call everything else for the main document:
<html><head>stuff</head>
<body>
<div>
<xsl:apply-templates/>
</div>
</body>
</html>
The problem is this works for the result-document title but none of the rest of the result-document templates are used, since they don't have mode="print" on them. So the rest of the result-document all comes out as text.
Any idea what I need to do here? I'm obviously missing something basic.
thank you
Scott

You have not shown any of the other templates but if you expect the <xsl:apply-templates mode="print"/> to apply them then you need to have a mode="#all" on them. And if they do additional apply-templates then you need to use <xsl:apply-templates select="#current"/>. See http://www.w3.org/TR/xslt20/#modes for details.

Related

XSL Template-match replace element

I have scoured the forums and and still not clear on this. I'm very new to the topic.
I have HTML output that is being sent to a browser email client (Outlook). Outlook overwrites the characteristics of the <p> tag and introduces large spacing.
I would like to set up a template-match to replace all <p> tags with <div> or <span>.
For complicated reasons which will not be addressed in this post, I cannot stop the HTML from being rendered with <p> tags in it.
So lets say that I have:
<p xmlns="http://www.w3.org/1999/xhtml">
<span>Some text</span>
</p>
I would want the output to be
<span>Some text</span>
with the <p> tags removed.
If I have
<p xmlns="http://www.w3.org/1999/xhtml">
<b>Some other text</b>
</p>
then I would be happy with either:
<b>Some other text</b>
or
<span>
<b>Some other text</b>
</span>
Just as long as it gets rid of the <p> tags.
It would also need to recognize <p> without any attributes.
I thought about something like
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<span>
<xsl:apply-templates select="#*|node()" />
</span>
</xsl:template>
but this does not work. The <p> tags still appear.
It is possible to write an adapter which will intercept the HTML before it is sent to the smtp server and manipulate it, but there are considerable difficulties in this approach which I am looking to avoid.
Is it even possible to do what I am attempting? Any help greatly appreciated.
Your input documents, this sample for instance:
<p xmlns="http://www.w3.org/1999/xhtml">
<span>Some text</span>
</p>
Have a default namespace. And that's a good thing because a valid XHTML document must be in a namespace.
This means that this namespace applies to all elements in the document by default, and you have to account for this in your XSLT stylesheet. Redeclare this namespace there:
<xsl:stylesheet xmlns:xhtml="http://www.w3.org/1999/xhtml">
and whenever you make a reference to an element from the input document, prefix the element with xhtml::
<xsl:template match="xhtml:p">
<span>
<xsl:apply-templates select="#*|node()" />
</span>
</xsl:template>
This should get you started. You have not told us yet if the output document should also be in a namespace or not.
Currently, only modifying the two templates you already have, a structure like
<p>
<span/>
</p>
will end up as
<span>
<span/>
</span>
Is this acceptable for you? If not, there must be an additional rule (template) about p elements that contain span elements:
<xsl:template match="xhtml:p[xhtml:span]">
or perhaps
<xsl:template match="xhtml:p[//xhtml:span]">

XSL template not being applied

Following is some XSL that I'm editing. I had to add code to account for html tables and cannot figure out why the templates under [CITATIONS] are being applied, but those under [TABLES] are not. The code for [CITATIONS] was there and working before I started. The code for [TABLES] I stole from another part of the application and where it does work just fine. Does anything here stand out to anyone? Thanks in advance.
<!-- Common template for procedure sub-sections. -->
<xsl:template match="th:section" priority="1" mode="procedures">
<div id="tab{position()}">
<xsl:if test="count(*//th:figure) gt 0">
<hr/>
<div class="carrousel floatbox">
<!-- LOTS OF CODE HERE. -->
</div>
<hr/>
</xsl:if>
<xsl:next-match/>
</div>
</xsl:template>
<!-- [TABLES] Table templates not being applied. -->
<xsl:template match="th:table" mode="procedures">
<table border="1">
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template match="th:thead">
<thead>
<xsl:apply-templates/>
</thead>
</xsl:template>
<!-- [More table templates follow here to handle table body and footer. None are being applied.] -->
<!-- [CITATIONS] These templates are being applied. -->
<xsl:template match="th:section[#type = 'literature']" mode="procedures">
<ol class="litrefs">
<xsl:apply-templates mode="refs"/>
</ol>
</xsl:template>
<xsl:template match="th:litref" mode="refs">
<li>
<xsl:apply-templates mode="refs"/>
</li>
</xsl:template>
<!-- [More templates follow here to handle citations. No problems here.] -->

Modifying XSL in xsltlistviewwebpart to render SharePoint 2010 ListItems as <ul> and <li> instead of <Table><tr><td>

I am trying to achieve what is mentioned in the title, but having trouble, need help.
I am modifying the following templates
1. <xsl:template name="View_Default_RootTemplate" mode="RootTemplate" match="View" ddwrt:dvt_mode="root" ddwrt:ghost="hide">
2. <xsl:template match="View" mode="full" ddwrt:ghost="hide">
3. <xsl:template mode="Item" match="Row" ddwrt:ghost="hide">
Q-1 Should i be modifying any other templates?
Desired end result - To render a recursive view and each list item as <li>listitem...</li> surrounded by a top level <ul>
Q-2 when i change the <table> elements to <ul> and <tr> to <li> the final page is still rendered with tables which i don't see in the templates and the <ul> & <li> changes are inserted into some unknown <td>, the questions are
a. What is the right way to do this? and what template is applied in this case?
Here's a simple example that should take care of it for you. You really only need the following two templates:
<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">
<xsl:call-template name="Main"/>
</xsl:template>
<xsl:template name="Main">
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row"/>
<ul>
<xsl:for-each select="$Rows">
<li>
<xsl:value-of select="#Title"/>
</li>
</xsl:for-each>
</ul>
</xsl:template>

XSLT/Diazo: create element for each pair of elements

I'm using Diazo/XSLT for theming a Plone website. On the homepage, Plone gives me the following structure:
<dl>
<dt>
The news item title
</dt>
<dd>
The content of the news item
</dd>
(and so on for the following ones)
</dl>
Which I want to transform into something like that:
<div id="news_items">
<div>
<h2>The news item title</h2>
The content of the news item.
<a class="readmore" href="<the HREF taken from the dt/a tag)">Read more</a>
</div>
(and so on for the following items)
</div>
I'm not really familiar with XSLT and Diazo (and more used to rewrite some pieces of existing themes) but I tried a few solutions.
The first one was to do this in two times. First look for each "dd" tags, creates the structure and after that update by parsing all "dt" tags:
<copy css:theme="#news_items">
<xsl:for-each css:select="#content-core dl dd">
<xsl:element name="div">
<xsl:element name="h2">
</xsl:element>
<xsl:copy-of select="./*" />
<xsl:element name="a">
<xsl:attribute name="class">readmore</xsl:attribute>
Read more
</xsl:element>
</xsl:element>
</xsl:for-each>
</copy>
It creates the structure correctly, but I don't know how to write the second part. The idea would be something like that:
<xsl:for-each css:select="#content-core dl dt">
<!-- Copy the link in the 'dd' tag into the h2 tag, based on the position -->
<copy css:theme="#news_item div:nth-child(position()) h2" css:select="a" />
<!-- Copy the a tag's href in the 'Read more' tag -->
<copy css:theme="#news_item div:nth-child(position()) a.readmore">
<xsl:attribute name="class">
<xsl:value-of select="#class" />
</xsl:attribute>
</copy>
</xsl:for-each>
I know it does not make that much sense, but I hope you get the idea of it:
I look into each "dd" tag
I find, based on the position in the loop, the 'h2' tag created in the previous step and I copy the link inside the "dd" tag.
I find (based on the position again) the "a.readmore" tag and copy the href.
The second solution I've been thinking about is a bit dirtier (and does not work either). The idea is to create the content in one step:
<xsl:for-each css:select="#content-core dl > *">
<xsl:if test="name = dt">
<!-- That the dt tag, we start the 'div' tag and add the h2 tag -->
</xsl:if>
<xsl:if test="name = dt">
<!-- That the dt tag, we copy the content and close the 'div' tag -->
</xsl:if>
</xsl:foreach>
But I really don't like the solution (and I don't see how to create the 'Read more' link).
Do you think the first solution can be done ? (especially the second step to populate the "h2" tag and add the "href" attribute on the "Read more" link).
Is there a way better solution available ?
I'd prefer to use only Diazo, but if it's not doable I can directly override the view in Plone (which would be simpler I think, at least I know how to do that)
Thanks for your help.
This transformation:
<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="/*">
<div id="news_items">
<xsl:apply-templates select="dt"/>
</div>
</xsl:template>
<xsl:template match="dt">
<div>
<h2><xsl:copy-of select="a"/></h2>
<xsl:apply-templates select="following-sibling::dd[1]"/>
<a class="readmore" href="{a/#href}">Read more</a>
</div>
</xsl:template>
</xsl:stylesheet>
when applied on the following XML document (with the same structure as the provided one but with more items):
<dl>
<dt>
The news item1 title
</dt>
<dd>
The content of the news item1
</dd>
<dt>
The news item2 title
</dt>
<dd>
The content of the news item2
</dd>
</dl>
produces the wanted, correct result:
<div id="news_items">
<div>
<h2>
The news item1 title
</h2>
The content of the news item1
<a class="readmore" href="someUrl1">Read more</a>
</div>
<div>
<h2>
The news item2 title
</h2>
The content of the news item2
<a class="readmore" href="someUrl2">Read more</a>
</div>
</div>

how XSLT convert tag inside tag?

I have the following XML
<title>
This is a <highlight>test</highlight> thanks.
</title>
and want to convert into
<span class="title">this is a <span class="highlight">test</span> thanks.</span>
I try this xslt, only can ge the text inside title tag, how can I also convert the highlight tag?
<span class="title"><xsl:value-of select="title"/></span>
<xsl:template match="title">
<span class="title">
<xsl:apply-templates />
</span>
</xsl:template>
<xsl:template match="highlight">
<span class="highlight">
<xsl:apply-templates />
</span>
</xsl:template>
or, if you want, collapse it into a single template:
<xsl:template match="title|highlight">
<span class="{name()}">
<xsl:apply-templates />
</span>
</xsl:template>
Key point is the <xsl:apply-templates /> - it runs all child nodes of the current node through the appropriate templates. In the upper variant, the appropriate templates are separate, in the lower variant the one template is called recursively.
There is a default rule defined in XSLT that copies text nodes. All text is run through this rule by <apply-templates>, so text nodes appear in the output autmatically.
Use xsl:copy-of instead of xsl:value-of if you want a full copy of the node and all of its children:
<span class="title"><xsl:copy-of select="title"/></span>
But for what you are trying to do, I would create one template for the title element and one for the highlight element:
<xsl:template match="title">
<span class="title"><xsl:value-of select="." /></span>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="highlight">
<span class="highlight"><xsl:value-of select="." /></span>
</xsl:template>