How to remove just an html anchor tag from a node being passed as a parameter in xslt? - templates

I have a data node that is being passed as a parameter in a template call, I want to strip out any html anchor tags but keep all other formatting html tags.
XML Data
<td class="ou-text-2"><p>The college's brand standards for logo treatment, font usage, and color usage, along with templates for PowerPoint presentations, memos, and email signatures. The downloadable Brand Standards Guide is available.</p></td>
Template Call XSL
<xsl:call-template name="remove-a">
<xsl:with-param name="description" select="tbody/tr[#class = 'ou-text']/td[#class = 'ou-text-2']"/>
</xsl:call-template>
Remove Anchor Tag Template XSL
<xsl:template name="remove-a">
<xsl:param name="description"/>
<xsl:choose>
<xsl:when test="$description/a">
<xsl:for-each select="$description/a/node()">
<xsl:copy-of select="normalize-space(.)"/>
</xsl:for-each> -->
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$description"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
I know the normalize-space function IS NOT what I need, but I don't know how to get what I need and that's just in there because it at least returns a value.
What I want to get
<p>The college's brand standards for logo treatment, font usage, and color usage, along with templates for PowerPoint presentations, memos, and email signatures. The downloadable Brand Standards Guide is available.</p>
What I'm getting
color usage Brand Standards Guide

Define a mode with the identity transformation as the base template and then add e.g. <xsl:template match="a"><xsl:apply-templates/></xsl:template> to handle the aelements.
Push any node you want to strip anchor elements from through that mode.

Related

Viewing an uploaded item in DSpace 4.2 xmlui

This is how the my search results page of DSpace looks like :
On clicking the item a new page opens up showing its description:
The description page opens the file upon clicking View/Open. Is it possible to directly open the file upon clicking its title on the results page? I want to skip the item description page.
As per my understanding this is the Java file which is called to render items. Do I need to make changes to this file? Or is it possible to achieve what I want by simply modifying the sitemap and xsl files?
The code that generates the thumbnail image is here.
https://github.com/DSpace/DSpace/blob/dspace-6_x/dspace-xmlui/src/main/webapp/themes/dri2xhtml/General-Handler.xsl#L34-L47
You could create similar logic to create an href to the original bitstream.
Look at the XML in /metadata/handle/xxx/yyy/mets.xml where xxx/yyy is your item handle. You should see the information that will point you to the original bitstream.
As was said in the comments, the xsl template to modify is the "itemSummaryList" in discovery.xsl
Replace that href value with $metsDoc//mets:FLocat[#LOCTYPE='URL']/#xlink:href"
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="$metsDoc//mets:FLocat[#LOCTYPE='URL']/#xlink:href"/>
</xsl:attribute>
<xsl:choose>
<xsl:when test="dri:list[#n=(concat($handle, ':dc.title')) and descendant::text()]">
<xsl:apply-templates select="dri:list[#n=(concat($handle, ':dc.title'))]/dri:item"/>
</xsl:when>
<xsl:otherwise>
<i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text>
</xsl:otherwise>
</xsl:choose>
</xsl:element>
I was able to achieve what I wanted with help from Antoine Snyers, terrywb and this link. As pointed out by terrywb the information which I needed to read, i.e, the bitstream address of the uploaded file, was stored in the metsDoc. Here's a screenshot of my metsDoc with the fileSec expanded:
To be able to access the fileSec of the metsDoc I changed this line in discovery.xsl and this line in common.xsl to <xsl:text>?sections=dmdSec,fileSec&fileGrpTypes=ORIGINAL,THUMBNAIL</xsl:text>.
Then I added/modified the following code to the itemSummaryList in discovery.xsl so that the title hyperlink now points to the file bitstream.
<xsl:variable name="filetype">
<xsl:value-of select="$metsDoc/mets:METS/mets:fileSec/mets:fileGrp[#USE='CONTENT']"/>
</xsl:variable>
<xsl:variable name="fileurl">
<xsl:value-of select="$metsDoc/mets:METS/mets:fileSec/mets:fileGrp[#USE='CONTENT']/mets:file/mets:FLocat[#LOCTYPE='URL']/#xlink:href"/>
</xsl:variable>
<div class="artifact-title">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:choose>
<xsl:when test="$metsDoc/mets:METS/mets:dmdSec/mets:mdWrap/mets:xmlData/dim:dim/#withdrawn">
<xsl:value-of select="$metsDoc/mets:METS/#OBJEDIT"/>
</xsl:when>
<xsl:when test="$filetype">
<xsl:value-of select="$fileurl"/>
</xsl:when>
</xsl:choose>
</xsl:attribute>
Similarly, I also made changes to item-list.xsl file, and added this line <xsl:apply-templates select="mets:fileSec/mets:fileGrp[#USE='CONTENT']"
mode="itemSummaryList-DIM"/> to the template itemSummaryList-DIM.
So finally I got my desired result:
As visible in the inspector, the href attribute of the title now points to the original bitstream of the file :)

Multi layer conditional wrap HTML with XSLT

In my Umbraco CMS site, I'm making a list of node "widgets" for content editors to use, with a list of many options they can toggle to change the display. This often involves wrapping an element with an anchor, div, or something else.
Using XSLT to display these from the XML output, I've put together what a kludge approach as I'm a very new XSLT beginner.
What I've come to as a solution is multiple nested apply-templates. This creates a large list of conditions, often asking repeat checks, which trees out pretty huge. It's a bit of a nightmare to manage.
It looks as such (but with more than two options in each choose):
<xsl:template match="/">
<xsl:choose>
<xsl:when test="type='1'">
<xsl:apply-templates select="widgetContent" mode="type_1" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="widgetContent" mode="type_default" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="wigetContent" mode="type_1">
<xsl:choose>
<xsl:when test="./wrap_with_hyperlink != 0">
<xsl:element name="a">
<xsl:apply-templates select="." mode="hyperlink_wrapped" />
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="widgetContent" mode="not_hyperlink_wrapped" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
What can I do to reduce this tangled mess? I've structured the conditions to be as top down as much as possible, but there are definitely repeated checks where type_2 has to ask the same questions as type_1 all over again.
(edit: clarity) Because the design is basically an onion, type_1 is wrapped by certain tags, type_2 is wrapped by different tags. Next layer in, both could be wrapped by the same tags, and so forth. What would be perfect is:
<xsl:if test="this_wrap_style = 1"><xsl:element name="abc"></xsl:if>
<xsl:if test="this_wrap_style = 2"><xsl:element name="xyz"></xsl:if>
(everything else)
</abc> //if it exist.
</xyz> //etc
Which definitely doesn't work.
Some of this has been reduced by using Umbraco Doc Types for different widget controls, but part of the nature is that to the ideal structure for content editors is selecting a box widget will give them 5 different types of widget boxes (or more) to choose from, and a coherent back end isn't as important.
Thank you all for your time.
<!--Store data in processing instruction nodes in a separate XML file-->
<?xml version='1.0' encoding="utf-8"?>
<root>
<?_1 div?>
<?_2 p?>
</root>
type_1 is wrapped by certain tags, type_2 is wrapped by different tags.
<xsl:variable name="divider" select="document('condition.xml')//processing-instruction(concat('_', $type) )" />
<xsl:variable name="equalizer" select="'span'"/>
<xsl:element name="{$divider}">
...
</xsl:element>
Next layer in, both could be wrapped by the same tags
<xsl:if test="contains('1,2',$type)">
<xsl:element name="{$equalizer}">
...
</xsl:element>
</xsl:if>

xslt matching and stripping

I have a XML structure like this, just some valid XML structure mixed with HTML tags. I am trying to match <p>MyHeader</p> in the section and set it to empty.
That is after running the XSLT on this structure, i don't want to print the <p>MyHeader</p> tag.
<abstract>
<section>
<p>MyHeader</p>
<p> other content in section </p>
<h1> other content in section </h1>
</section>
</abstract>
Here's what I am trying in the XSL
<xsl:template match="abstract/section/p">
<xsl:choose>
<xsl:when test="text() ='MyHeader'"></xsl:when>
<xsl:otherwise><xsl:apply-templates /></xsl:otherwise>
</xsl:choose>
</xsl:template>
any ideas on what's wrong with my code above? I dont see <p>MyHeader</p> tag being stripped out.
<xsl:template match="abstract/section/p">
<xsl:choose>
<xsl:when test="text() ='MyHeader'"></xsl:when>
<xsl:otherwise><xsl:apply-templates /></xsl:otherwise>
</xsl:choose>
</xsl:template>
what's wrong with my code
Nothing wrong with the code shown -- the problem is in the code you haven't shown to us.
Guessing:
The template isn't selected for execution.
There is an explicit <xsl:copy-of> selecting this p element.
Recommendation: just use:
<xsl:template match="abstract/section/p[.='MyHeader']"/>

avoid mismatched tags outputting HTML with XSLT

I'm new to XSLT, and there's one specific thing I don't know how to do, despite hours of searching for the answer.
I'm outputting blocks of HTML (result sets), and sometimes the result is a hyperlink, sometimes it is not.
The simple flow looks like this:
<a...> if #url
some HTML code
</a> if #url
But if I do:
when #url
<a...>
/when
some HTML code
when #url
</a>
/when
... I'm told that I have mismatched tags.
I was using CDATA text for the anchor set, but a lot of messages say that this is a "hack" approach.
I'm trying to avoid having to repeat the entire HTML code block only to include the anchors on only one of them.
How do I do this?
-------edit / additional info-----------
Does this make more sense?
<xsl:template match="Row">
<xsl:choose>
<xsl:when test="#url!=''">
<a><xsl:attribute name="href"><xsl:value-of select="#url" /></xsl:attribute>
</xsl:when>
</xsl:choose>
<img />
<xsl:choose>
<xsl:when test="#url!=''">
</a>
</xsl:when>
</xsl:choose>
</xsl:template>
In XSLT, your output is a tree of nodes. Writing an element node is a single atomic operation; it can't be split into separate operations of writing a start tag and writing an end tag. You can't create half a node.
If you do try to treat <a> and </a> as separate and separable operations, you will get this error, because the stylesheet must be well-formed XML.
So, stand back and explain what you are trying to achieve, and then we can tell you how to achieve it properly in XSLT.
One way to refactor the XSLT to conditionally apply the hyperlink and not repeat the logic to produce the <img/> (or whatever more complex logic you are trying to avoid repeating) is to extract that logic out into a different template(s) as either a named template or a template with a #mode.
For instance:
<xsl:template match="Row">
<xsl:choose>
<xsl:when test="#url!=''">
<a>
<xsl:attribute name="href">
<xsl:value-of select="#url"/>
</xsl:attribute>
<xsl:apply-templates select="." mode="image"/>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="image"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!--The "common" logic to produce an image element, whether or not it will be surrounded by an anchor linking to the #url -->
<xsl:template match="Row" mode="image">
<img/>
</xsl:template>
An alternative way of accomplishing the same thing, but using templates instead of <xsl:choose>:
<xsl:template match="Row[#url]">
<a href="#url">
<xsl:apply-templates select="." mode="image"/>
</a>
</xsl:template>
<xsl:template match="Row">
<xsl:apply-templates select="." mode="image"/>
</xsl:template>
<xsl:template match="Row" mode="image">
<img/>
</xsl:template>

Hyperlinks within XSLT Templates

I am trying to create hyperlinks using XML information and XSLT templates. Here is the XML source.
<smartText>
Among individual stocks, the top percentage gainers in the S. and P. 500 are
<smartTextLink smartTextRic="http://investing.domain.com/research/stocks/snapshot
/snapshot.asp?ric=HBAN.O">Huntington Bancshares Inc</smartTextLink>
and
<smartTextLink smartTextRic="http://investing.domain.com/research/stocks/snapshot
/snapshot.asp?ric=EK">Eastman Kodak Co</smartTextLink>
.
</smartText>
I want the output to look like this, with the company names being hyperlinks based on the "smartTextLink" tags in the Xml.
Among individual stocks, the top percentage gainers in the S.&P. 500 are Eastman Kodak Co and Huntington Bancshares Inc.
Here are the templates that I am using right now. I can get the text to display, but not the hyperlinks.
<xsl:template match="smartText">
<p class="smartText">
<xsl:apply-templates select="child::node()" />
</p>
</xsl:template>
<xsl:template match="smartTextLink">
<a>
<xsl:apply-templates select="child::node()" />
<xsl:attribute name="href">
<xsl:value-of select="#smartTextRic"/>
</xsl:attribute>
</a>
</xsl:template>
I have tried multiple variations to try to get the hyperlinks to work correctly. I am thinking that the template match="smartTextLink" is not being instantiated for some reason. Does anyone have any ideas on how I can make this work?
EDIT: After reviewing some of the answers, it is still not working in my overall application.
I am calling the smartText template from within my main template
using the following statement...
<xsl:value-of select="marketSummaryModuleData/smartText"/>
Could this also be a part of the problem?
Thank you
Shane
Either move the xsl:attribute before any children, or use an attribute value template.
<xsl:template match="smartTextLink">
<a href="{#smartTextRic}">
<xsl:apply-templates/>
</a>
</xsl:template>
From the creating attributes section of the XSLT 1 spec:
The following are all errors:
Adding an attribute to an element after children have been added to it; implementations may either signal the error or ignore the attribute.
Try this - worked for me:
<xsl:template match="smartText">
<p class="smartText">
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="smartTextLink">
<a>
<xsl:attribute name="href">
<xsl:value-of select="#smartTextRic"/>
</xsl:attribute>
<xsl:value-of select="text()"/>
</a>
</xsl:template>
Trick is - <xsl:attribute> first, before you do any other processing.
Marc