I've trying to edit item-view.xsl to add a link in author label (dc.contributor.author) but no luck yet.
I'm using XMLUI - Mirage2
Author link example image
in: https://openknowledge.worldbank.org/handle/10986/29498
What should I add?
Thanks
The following code snippet might help. This code turns the subject field into a facet link. It will require a little modification to work for the author field.
<xsl:variable name="H_SUBJECT">Subject</xsl:variable>
<xsl:variable name="DFILTER_SUBJECT">/discover?filtertype=subject&filter_relational_operator=equals&filter=</xsl:variable>
<xsl:template name="itemSummaryView-DIM-subject">
<xsl:if test="dim:field[#element='subject']">
<div class="simple-item-view-description item-page-field-wrapper table">
<h5><xsl:value-of select="$H_SUBJECT"/></h5>
<div>
<xsl:for-each select="dim:field[#element='subject']">
<xsl:choose>
<xsl:when test="node()">
<a class="gu-subject-link" href="{concat($FILTER_SUBJECT,.)}">
<span>
<xsl:apply-templates select="." mode="microtag-prop"/>
<xsl:apply-templates select="text()"/>
</span>
</a>
</xsl:when>
<xsl:otherwise>
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="count(following-sibling::dim:field[#element='subject']) != 0">
<xsl:text>; </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:if test="count(dim:field[#element='subject']) > 1">
<xsl:text>; </xsl:text>
</xsl:if>
</div>
</div>
</xsl:if>
</xsl:template>
I have been researching and haven't been able to find anything related to optimizing XSLT. Below is the snippet that I am working on and wanted to see if anything can be done to help with the xslt transformation.
<xsl:template match="a:OBR/*">
<xsl:choose>
<xsl:when test ="name() = 'OBR-10' and string-length(.) = 0">
<OBR-10>USER</OBR-10>
</xsl:when>
<xsl:when test ="name() = 'OBR-18'">
<OBR-18>
<xsl:value-of select ="//a:PV1/a:PV1-44"/>
</OBR-18>
</xsl:when>
<xsl:when test ="name() = 'OBR-19'">
<OBR-19>
<xsl:if test = "string-length(str:tokenize(../a:OBR-18,'^')[5]) > 0">
<xsl:value-of select ="str:tokenize(../a:OBR-18,'^')[5]"/>
</xsl:if>
</OBR-19>
</xsl:when>
<xsl:when test ="name() = 'OBR-33'">
<OBR-33>
<xsl:value-of select ="translate(../parent::a:ORC[1]/a:ORC-4,'^','~')"/>
</OBR-33>
</xsl:when>
<xsl:when test="name()='NTE'">
<NTE>
<xsl:apply-templates/>
</NTE>
</xsl:when>
<xsl:when test="name()='DG1'"/>
<!--<DG1>
<xsl:apply-templates/>
</DG1>
</xsl:when>-->
<xsl:when test="name()='OBX'">
<OBX>
<xsl:apply-templates/>
</OBX>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
I would suggest to write code like
<xsl:template match="a:OBR/*">
<xsl:choose>
<xsl:when test ="name() = 'OBR-10' and string-length(.) = 0">
<OBR-10>USER</OBR-10>
</xsl:when>
as
<xsl:template match="a:OBR/OBR-10[string-length() = 0]">
<xsl:copy>USER</xsl:copy>
</xsl:template>
or perhaps
<xsl:template match="a:OBR/OBR-10[. = '']">
<xsl:copy>USER</xsl:copy>
</xsl:template>
that is, to write templates that match each element by its name and if needed a predicate/condition instead of that odd approach to match on * and then test the name. I don't see that necessarily as an optimization (you would have to measure with a particular implementation) but as a clear and modular coding style.
The
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
would then be code as
<xsl:template match="a:OBR/*">
<xsl:copy-of select="."/>
</xsl:template>
or probably already covered by an identity transformation template set up as the starting point to initiate and keep up the processing.
You would have to show the namespaces in the input document and the XSLT to allow a precise suggestion in terms of namespaces (could be that you want/need xsl:template match="a:OBR/a:OBR-10[string-length() = 0]").
This is my XML:
<LIGHT_INFORMATION_LIST>
<LIGHT_INFORMATION>
<LIGHT_CHARACTERISTICS>Al</LIGHT_CHARACTERISTICS>
<LIGHT_COLOUR>W-G</LIGHT_COLOUR>
</LIGHT_INFORMATION>
<LIGHT_INFORMATION>
<LIGHT_CHARACTERISTICS>Al</LIGHT_CHARACTERISTICS>
<LIGHT_COLOUR>W-R</LIGHT_COLOUR>
</LIGHT_INFORMATION>
<LIGHT_INFORMATION>
<LIGHT_CHARACTERISTICS>F</LIGHT_CHARACTERISTICS>
<LIGHT_COLOUR>R</LIGHT_COLOUR>
</LIGHT_INFORMATION>
<LIGHT_INFORMATION>
<LIGHT_CHARACTERISTICS>F</LIGHT_CHARACTERISTICS>
<LIGHT_COLOUR>G</LIGHT_COLOUR>
</LIGHT_INFORMATION>
<LIGHT_INFORMATION>
<LIGHT_CHARACTERISTICS>F</LIGHT_CHARACTERISTICS>
<LIGHT_COLOUR>W</LIGHT_COLOUR>
</LIGHT_INFORMATION>
</LIGHT_INFORMATION_LIST>
I woul insert a control:
if at least one element of LIGHT_COLOUR into this LIGHT_INFORMATION_LIST contain '-'
I tried whit this, but is completely wrong:
<xsl:choose>
<xsl:when test="not(contains(.,'-'))">
<!-- do A -->
</xsl:when>
<xsl:otherwise>
<!-- do B -->
</xsl:otherwise>
</xsl:choose>
This is actually my XSLT code:
<xsl:for-each select="LIGHT_INFORMATION">
<xsl:for-each select="LIGHT_COLOUR">
<xsl:choose>
<xsl:when test="not(contains(.,'-'))"> <!-- This is the test Required -->
<xsl:choose>
<xsl:when test="following-sibling::LIGHT_RANGE >= 15">
<span style="font-family:Univers Condensed; font-weight:bold;">
<xsl:if test="not(preceding::LIGHT_COLOUR[1][preceding::IMMUTABLE_ID = $EF])">
<xsl:value-of select="."/>
</xsl:if>
<xsl:if test=". != preceding::LIGHT_COLOUR[1][preceding::IMMUTABLE_ID = $EF]">
<xsl:value-of select="."/>
</xsl:if>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:if test="not(preceding::LIGHT_COLOUR[1][preceding::IMMUTABLE_ID = $EF])">
<xsl:value-of select="."/>
</xsl:if>
<xsl:if test=". != preceding::LIGHT_COLOUR[1][preceding::IMMUTABLE_ID = $EF]">
<xsl:value-of select="."/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
ciao <!-- I would insert this control here if LIGHT_COLOUR contain '-' -->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:for-each>
Now the output is:
ciao ciao R G W
I would, if only one element in this node of LIGHT_INFORMATION_LIST contains into LIGHT_COLOUR '-' write 'Ciao'
Thi is the solution:
<xsl:for-each select="LIGHT_INFORMATION">
<xsl:choose>
<xsl:when test="not(contains(parent::LIGHT_INFORMATION_LIST//LIGHT_COLOUR, '-'))"> <!-- This is the solution -->
<xsl:for-each select="LIGHT_COLOUR">
<xsl:choose>
<xsl:when test="following-sibling::LIGHT_RANGE >= 15">
<span style="font-family:Univers Condensed; font-weight:bold;">
<xsl:if test="not(preceding::LIGHT_COLOUR[1][preceding::IMMUTABLE_ID = $EF])">
<xsl:value-of select="."/>
</xsl:if>
<xsl:if test=". != preceding::LIGHT_COLOUR[1][preceding::IMMUTABLE_ID = $EF]">
<xsl:value-of select="."/>
</xsl:if>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:if test="not(preceding::LIGHT_COLOUR[1][preceding::IMMUTABLE_ID = $EF])">
<xsl:value-of select="."/>
</xsl:if>
<xsl:if test=". != preceding::LIGHT_COLOUR[1][preceding::IMMUTABLE_ID = $EF]">
<xsl:value-of select="."/>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
Ciao
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
Insert the control at the head and using PARENT.
following-sibling would only find a LIGHT_COLOR if it were on the same level (ie the current node was a LIGHT_CHARACTERISTIC node and even then it would only ever find one.
To look at all of them, you need to specify a path that includes them all, either globally or relative to the current node. In this case:
/LIGHT_INFORMATION_LIST/LIGHT_INFORMATION/LIGHT_COLOUR
This path will select all LIGHT_COLOR nodes. Now we want to filter out each node if it does not contain a "-":
/LIGHT_INFORMATION_LIST/LIGHT_INFORMATION/LIGHT_COLOUR[contains(., "-")]
We aren't actually interested in any of the individual nodes, we just want to know how many there are so:
count (/LIGHT_INFORMATION_LIST/LIGHT_INFORMATION/LIGHT_COLOUR[contains(., "-")])
Therefore, your check would be:
<xsl:when test='count (/LIGHT_INFORMATION_LIST/LIGHT_INFORMATION/LIGHT_COLOUR[contains(., "-")])'>
* Edit: Revised answer to revised question *
If you want one control, then you only want to do it once so move it outside of the loop:
<!-- Do this where we can see all of the LIGHT_COLOR tags -->
<xsl:if test="contains(LIGHT_INFORMATION/LIGHT_COLOR, '-')">
Ciao
</xsl:if>
<xsl:for-each select="LIGHT_INFORMATION">
<!-- as per your existing code. Remove the "otherwise" clause that is creating multiple controls. -->
Hi i've the below xslt for creating anchor tags.
<xsl:template match="para/text()">
<xsl:variable name="numx">
<xsl:number format="1" level="any"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="(contains(substring(substring-after(current(),'.'),4,1),')') or contains(substring(substring-after(current(),'.'),4,1),'.') or contains(substring(substring-after(current(),'.'),4,1),' ')) and (contains(substring (current(),string-length(substring-before(current(), '.')) -1,2),' ')) and contains(substring(current(),string-length(substring-before(current(), '.')) -2,1),$numx)">
<xsl:variable name="before">
<xsl:value-of select="normalize-space(substring(current(),string-length(substring-before(current(), '.')) -1,2))"/>
</xsl:variable>
<xsl:variable name="NewN">
<xsl:value-of select="concat('0',$before)"/>
</xsl:variable>
<xsl:variable name="after">
<xsl:value-of select="substring(substring-after(current(),'.'),1,3)"/>
</xsl:variable>
<xsl:variable name="befdNumb">
<xsl:value-of select="substring-before(current(),$before)"/>
</xsl:variable>
<xsl:variable name="aftdNumb">
<xsl:value-of select="substring-after(current(),$after)"></xsl:value-of>
</xsl:variable>
<xsl:value-of select="$befdNumb"/>
<xsl:text> </xsl:text>
<a href="{concat('er:#CLI_CH_',$NewN,'/','P',normalize-space($before),'-',$after)}">
<xsl:value-of select="concat(normalize-space($before),'.',$after)"/>
</a>
<xsl:value-of select="$aftdNumb"/>
</xsl:when>
<xsl:when test="(contains(substring(substring-after(current(),'.'),4,1),')') or contains(substring(substring-after(current(),'.'),4,1),'.') or contains(substring(substring-after(current(),'.'),4,1),' ')) and contains(substring (current(),string-length(substring-before(current(), '.')) -2,1),' ')">
<xsl:variable name="before">
<xsl:value-of select="substring(current(),string-length(substring-before(current(), '.')) -2,3)"/>
</xsl:variable>
<xsl:variable name="NewN">
<xsl:value-of select="$before"/>
</xsl:variable>
<xsl:variable name="after">
<xsl:value-of select="substring(substring-after(current(),'.'),1,3)"/>
</xsl:variable>
<xsl:variable name="befdNumb">
<xsl:value-of select="substring-before(current(),$before)"/>
</xsl:variable>
<xsl:variable name="aftdNumb">
<xsl:value-of select="substring-after(current(),$after)"></xsl:value-of>
</xsl:variable>
<xsl:value-of select="$befdNumb"/>
<xsl:text> </xsl:text>
<a href="{concat('er:#CLI_CH_',$NewN,'/','P',normalize-space($before),'-',$after)}">
<xsl:value-of select="concat(normalize-space($before),'.',$after)"/>
</a>
<xsl:value-of select="$aftdNumb"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
but this xslt is getting applied i.e. the anchor tag is getting created if the text is like below.(having only '.' in the entire text).
serving on the company, by one of the means discussed at paragraph 12.012 below, a demand signed by the creditor
but i want it o be applied for the below text also
<para>the major issues here concern the notion of principal and ancillary jurisdictions, the ideal being that the ancillary jurisdiction will defer to the principal jurisdiction on most important matters, with a view to bringing about a just, practical and economically rational winding-up of affairs. A relatively recent development in connection with that ideal concerns the judicial promotion of court-endorsed agreements known as "crossborder protocols" between liquidators and similar officers appointed in different jurisdictions. It is important in this context, however, not to lose sight of the fact that certain matters of "administration" always remain governed by Hong Kong law. See paragraphs 12.016 to 12.032 below.</para>
please let me know how do i do it. i need to convert this number as er:#CLI_CH_12/P12-016 and er:#CLI_CH_12/P12-032
Thanks
I'm quite sure there could be a better way dot this, but because it is not entirely clear what this xslt should do I stay with your solution.
You need to do some recursive template calls.
Change your current "para/text()" template to a named template with text as an parameter.
But replace every current() with $text
<xsl:template name="mytext">
<xsl:param name="text" />
<xsl:variable name="numx">
<xsl:number format="1" level="any"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="(contains(substring(substring-after($text,'.'),4,1),')')
or contains(substring(substring-after($text,'.'),4,1),'.')
or contains(substring(substring-after($text,'.'),4,1),' '))
and (contains(substring ($text,string-length(substring-before($text, '.')) -1,2),' '))
and contains(substring($text,string-length(substring-before($text, '.')) -2,1),$numx)">
....
</xsl:template>
Add a new template to call the named one with the current text().
<xsl:template match="para/text()">
<xsl:call-template name="mytext" >
<xsl:with-param name="text" select="." />
</xsl:call-template>
</xsl:template>
Add an when just before the otherwise to output the text before a not handled dot and call the named template with text behind this dot.
<xsl:when test="contains(substring-after($text,'.'),'.')">
<xsl:value-of select="substring-before($text,'.')"/>
<xsl:text>.</xsl:text>
<xsl:call-template name="mytext">
<xsl:with-param name="text" select="substring-after($text,'.')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
I'm a complete XSL novice, writing an XSL file to format lots of different error messages that can appear in the output log created by an application into CSV format.
Slight variations might occur in the matchable tags in these output logs. For example, one sentence in the log might contain the phrase "Service Month/Year:" but another one, from a different area of the application, would contain "Svc Month/Yr:" instead.
Is there a way to put both those variations of that phrase in a single line of my XSL? Or do I have to repeat the entire If block, with each variation in the phrase that I want to match on in its own If block?
I tried posting the XSL here surrounded by backticks, but it runs all together in one big lump that's impossible to read. If anyone can help with this question, I'm happy to post it if you tell me how to make it readable. :-)
Thank you.
XSL allows combining of conditional statements like other langues. Each one doesn't require its on if statement. Were you thinking something along these lines?
<xsl:choose>
<xsl:when test="contains(text(), 'Service Month/Year:')
or contains(text(), 'Svc Month/Yr:')
">
<!-- do something -->
</xsl:when>
</xsl:choose>
Keep in mind xml/xsl is case sensitive. To make it more flexible, it is even more verbose:
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:choose>
<xsl:when test="contains(translate(text(), $upper, $lower), 'service month/year:')
or contains(translate(text(), $upper, $lower), 'svc month/yr:')
">
<!-- do something -->
</xsl:when>
</xsl:choose>
EDIT: And an even better answer I whipped up
<xsl:template name="containsToken">
<xsl:param name="inputString"/>
<xsl:param name="tokens"/>
<xsl:param name="delimiter"/>
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:choose>
<xsl:when test="contains($tokens, $delimiter)">
<xsl:variable name="token">
<xsl:value-of select="substring-before($tokens, $delimiter)"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="contains(translate($inputString, $upper, $lower), translate($token, $upper, $lower))">
<xsl:text>True</xsl:text>
</xsl:when>
<xsl:otherwise>
<!-- loop -->
<xsl:call-template name="containsToken">
<xsl:with-param name="inputString" select="$inputString"/>
<xsl:with-param name="tokens" select="substring-after($tokens, $delimiter)"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="contains(translate($inputString, $upper, $lower), translate($tokens, $upper, $lower))">
<xsl:text>True</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>False</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
Usage:
<xsl:variable name="found">
<xsl:call-template name="containsToken">
<xsl:with-param name="inputString" select="text()"/>
<xsl:with-param name="tokens" select="'Service Month/Year:|Svc Month/Yr:'"/>
<xsl:with-param name="delimiter" select="'|'"/>
</xsl:call-template>
</xsl:variable>
<xsl:if test="$found = 'True'">
<!-- process -->
</xsl:if>
Delimiter can be whatever character or charcters you want. Tokens is a list of things to search for with the delimiter between each one. Enjoy!