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 :)
Related
I have the following XSL which I render into my HTML:
<xsl:for-each select="user">
<xsl:variable name="exampleurl">
<xsl:choose>
<xsl:when test="objecttype='2'">
Check this out:
<strong><a class="link" href="http://www.example.com/beinspired">Inspiration</a></strong>.
</xsl:when>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$exampleurl" />
</xsl:for-each>
However, when I print the variable $exampleurl only the text "Check this out: Inspiration." is printed. But the word "Inspiration" is not a clickable URL like I would want.
How to fix this?
value-of creates a text node, you want
<xsl:copy-of select="$exampleurl" />
(or of course in this case you don't need a variable at all, but I assume that's just the small example?
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>
I am creating a summary view of Microsoft InfoPath form(s) using a custom XSLT Stylesheet.
I have a selection of the radio buttons on the form which are clicked "Yes", "No"
e.g.
What is the primary construction of the building?
Steel Yes
No
Timber Yes
NO
etc....
In the stylesheet I have
<tr>
<td>
The primary contruction of the building is
<xsl:choose>
<xsl:when test="/my:myFields/my:BrickPrimaryConstruction= 'true'">
Brick
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="/my:myFields/my:TimberPrimaryConstruction = 'true'">
Timber Framed
</xsl:when>
</xsl:choose>
<xsl:choose>
<xsl:when test="/my:myFields/my:ConcretePrimaryConstruction = 'true'">
Concrete Framed
</xsl:when>
</xsl:choose>
etc....
What I want to achieve in the final HTML output is something like:
The primary construction of the building is Brick, Concrete Framed, Prefabricated
I have not got much experience of XSLT, but what is the best way of achieving this?
Avoiding this:
, Concrete Framed, Prefabricated,
or
Brick, , Prefabricated
Normally in C# I would assign to a string and check if it is empty before appending a comma and then trim commas on the ends however I know that I cannot assign variables in xslt.
EDIT
I also mentioned that I wanted to be able to reuse the function in other situations such as
<xsl:value-of select="/my:myFields/my:Road"/>,
<xsl:value-of select="/my:myFields/my:District"/>,
<xsl:value-of select="/my:myFields/my:City"/>,
<xsl:value-of select="/my:myFields/my:County"/>,
<xsl:value-of select="/my:myFields/my:Postcode"/>
where these would be separated by comma or a new line character, but there is the possibility that the "District" for example might be blank resulting in "Road, , City" etc.
Try this:
<tr>
<td>
The primary contruction of the building is
<xsl:for-each select="/my:myFields/my:*[ends-with(local-name(), 'PrimaryConstruction') and (.='true')]">
<xsl:if test="position()!=1" xml:space="preserve">, </xsl:if>
<xsl:choose>
<xsl:when test="self::my:BrickPrimaryConstruction">Brick</xsl:when>
<xsl:when test="self::my:TimberPrimaryConstruction">Timber Framed</xsl:when>
<xsl:when test="self::my:ConcretePrimaryConstruction">Concrete Framed</xsl:when>
etc...
</xsl:choose>
</xsl:for-each>
Basically, the for-each loops over all the relevant fields, so that you can check their position and only emit the comma if you're not on the first item (XSLT has a 1-based index). Since the for-each already filters only the relevant entries, we then only have to check the type, not whether the value is true or not.
Note that you can extend the same principle to emit an "and" for the last item instead of a comma if you like to do so.
Maybe look at Implode.
Then, you could do
<xsl:variable name="theItems">
<xsl:if test="/my:myFields/my:BrickPrimaryConstruction= 'true'">
<foo>Brick</foo>
</xsl:if>
</xsl:variable>
<xsl:call-template name="implode">
<xsl:with-param name="items" select="exsl:node-set($theItems)" />
</xsl:call-template>
You have to convert $theItems, which is a xml fragment, to a node-set. This can only be archived using non-standart methods. XML.com shows some methods to archive it using various XML processors.
Is there a way to open a tag and not close it? For example:
<xsl:for-each select=".">
<span>
</xsl:for-each>
This is my code: http://pastebin.com/1Xh49YN0 . As you can see i need to open on a when tag and close it on another when tag (row 43 and 63).
This piece of code is not valid because XSLT is not well formed, but is there a way to do a similar thing? Thank you
Move the content between the two existing xsl:choose elements to a new template
In the xsl:when, open and close your span. Inside the span, call this new template.
Add an xsl:otherwise to the xsl:choose, in this, call the template, without adding a span.
As a general point, try to use xsl:apply-templates a bit more often, rather than xsl:for-each, it should make it easier to understand what is going on.
You can't - XSLT isn't about generating a text file or a sequence of characters, it's about transforming one document tree into another. That the tree eventually gets serialized into a textual format is incidental.
This is why, for example, you can't choose between and in the output file - they're both represent exactly the same document tree.
You can almost always achieve what is intended by refactoring into separate templates that call each other.
You can use disable-output-escaping, but it's generally considered a bit of a hack, and I understand it's deprecated in XSLT 2.
Untested, obviously, but if I understood your original code correctly, this should be pretty close.
<xsl:choose>
<xsl:when test="$pos">
<xsl:for-each select="$s">
<xsl:choose>
<!-- inizio contesto -->
<xsl:when test="$pos[.=position()+$context_number]">
<xsl:text>INIZIO CONTESTO</xsl:text>
</xsl:when>
<!-- fine contesto -->
<xsl:when test="$pos[.=position()-$context_number]">
<xsl:text>FINE CONTESTO</xsl:text>
</xsl:when>
<!-- parola -->
<xsl:when test="$pos[.=position()]">
<span class="word"><xsl:value-of select="."/></span>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="position() != last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<!-- stampo tutta la riga -->
<xsl:value-of select="$s"/>
</xsl:otherwise>
</xsl:choose>
Hint: <xsl:when test="(. - $current_pos) eq 0"> is equivalent to <xsl:when test=".=$current_pos">. ;-)
I need help please.
No clue in xml & WebtextEdit, I am editing an xslt stylesheet that creates asp controls.
Below is the WebTextEdit control, I want to add an mousemove event:
<xsl:element name="igtxt:WebTextEdit">
<xsl:attribute name='id'><xsl:value-of select='$Name' /></xsl:attribute>
<xsl:attribute name='runat'>server</xsl:attribute>
<xsl:attribute name='Text'><xsl:value-of select='$Value' disable-output-escaping="yes" /></xsl:attribute> <xsl:attribute name='MouseMove'>"<xsl:value-of select='#name' />".style.color = '#006AB6';</xsl:attribute>
<xsl:for-each select="$Attributes/Attribute">
<xsl:if test=". != ''">
<xsl:attribute name='{#name}'><xsl:value-of select='.' /></xsl:attribute>
</xsl:if>
</xsl:for-each>
<xsl:copy-of select="$Events" />
</xsl:element>
The code works to change the style as it works on other objects.
Please assist with how i can add a mouseover event to WebTextEdit control
If you always want to run the same (static) JavaScript or dynamic JavaScript generated with XSLT, use the same method as is used to add the id, runat, and Text attributes:
<xsl:attribute name="mouseover">alert('test');</xsl:attribute>
If each control needs to execute different (static) JavaScript, just add an onmouseover attribute to the XML element that triggers this template. The loop will read any attributes in the XML element and pass them on to the generated markup.