How to easily generate unique strings in XSLT? - xslt

I have a question!
I have an XML document that has sections and subsections. I am generating a Doxygen page out of it using XSLTProc and now I have a problem. When I generate a section name like this:
<xsl:template match="SECTION/SUBSECTION">
#subsection <xsl:value-of select="#title"/>
<xsl:apply-templates/>
</xsl:template>
Then the first word of the title does not show up, because Doxygen expects the declaration in this way:
#subsection <subsectionname> <subsectiontitle>
So, the first word is automatically treated as the subsection name. Putting a randomly generated string there does not seem like a very simple task. I tried to put unique number instead, by using <xsl:value-of select="count(preceding-sibling::*[#col]) + 1", which worked as expected, but as it turns out, Doxygen does not accept numbers as subsection names. I also tried to strip white spaces of "#title" and use that as the subsection name, but XSLTProc complains that it was not an immediate child of <xslt:stylesheet>. How can I easily put some unique string there? It does not have to be meaningful text.
Thanks in advance!

Use the generate-id() function.
<xsl:value-of select="generate-id(#title)"/>
If you want the generated string to be more "readable", here is one way to do this:
<xsl:value-of select="concat(#title, generate-id(#title))"/>

Related

How to strip Unicode soft hyphen from PDF bookmarks generated using XSL-FO

I'm converting DITA maps to PDF using the DITA Open Toolkit 1.7 and RenderX XEP. In the DITA topics, product names are inserted using conrefs. One of my product names is quite long. It caused layout problems when used within tables. Therefore I inserted a soft hyphen into the phrase that is reused via conref:
<ph id="PD_FineReader2Comp">DOXiS4 FineReader2­Components</ph>
This works nicely in the generated pages, but creates a problem in the bookmarks where a symbol is displayed in place of the soft hyphen.
Obviously, this is an encoding problem. It seems that UTF-8 characters are properly handled in PDF content, but not in PDF bookmarks where, according to the following sources, some PDF-16 characters can be used (but I did not understand which ones).
http://partners.adobe.com/public/developer/en/pdf/PDFReference.pdf
http://www.setasign.de/support/tips-and-tricks/use-unicode-in-string-values/
The DITA Open Toolkit seems to create bookmarks from topic titles using this code fragment:
<fo:bookmark>
<xsl:attribute name="internal-destination">
<xsl:call-template name="generate-toc-id"/>
</xsl:attribute>
<xsl:if test="$bookmarkStyle!='EXPANDED'">
<xsl:attribute name="starting-state">hide</xsl:attribute>
</xsl:if>
<fo:bookmark-title>
<xsl:value-of select="normalize-space($topicTitle)"/>
</fo:bookmark-title>
<xsl:apply-templates mode="bookmark"/>
</fo:bookmark>
The XSL stylesheet has version 2.0.
I would like to create an override that removes the offending character. How can I do this?
Is it possible to properly resolve the encoding problem? (Probably not possible).
Are there any XSL functions or attributes which remove whitespace other than space, tab, linefeed, and carriage return?
Or do I need special handling for the soft hyphen?
Small refinement: If you are using XSLT2, will be more efficient than in this context. In XSLT2 you should always prefer xsl:sequence over xsl:value-of
The simple way to do this is to use the translate() function, which can be used to replace certain characters with other characters, or with nothing. It looks like this is the line that outputs the value you want to fix up:
<xsl:value-of select="normalize-space($topicTitle)"/>
So you could simply modify this to:
<xsl:value-of select="translate(normalize-space($topicTitle), '­', '')"/>
to remove all the soft hyphens. If you would like to replace them with spaces or ordinary hyphens, you could do either of the following, respectively:
<xsl:value-of select="translate(normalize-space($topicTitle), '­', ' ')"/>
<xsl:value-of select="translate(normalize-space($topicTitle), '­', '-')"/>

Replace or append to link

I am working on an old Sitecore 4 solution where i need to manipulate the output of a field slightly. I have a normal field (Message) that i am outputting via <sc:html field="message"/> or <xsl:value-of select="sc:fld('Message',.)"/>.
Either works just fine.
I now have to search in the "Message" field for links, and then i need to append the date to the end of the link like so "this is my link
How could i accomplish the above in XSLT 1.0?
My understanding is that you want to do a find and convert urls to links.
I see these as your Options:
1. Xpath 2.0 supports functions like matches and replace which use regular expressions. See http://www.w3schools.com/xpath/xpath_functions.asp#string or http://www.w3.org/TR/xpath-functions/#func-replace. I'm not sure if sitecore supports Xpath 2.0. From memory i dont think it supports Xpath 2.0. If it does you are in luck and you can do something similar like this
<xsl:choose>
<xsl:when test="contains(., 'http.*')">
<strong><xsl:value-of select="replace(.,'http.*','REPLACED TEXT')"/></strong>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="."/>
</xsl:otherwise>
</xsl:choose>
Find and replace the Message values before or after it gets to XSL transformation just before you render the output.
Things to what out for:
Why do you have URLs without showing up as Links in Message tag? Is it a case where you are not using WYSIWYG for content?
If this seems to be too much work, which sounds like it is. You can have a workaround to have a javascript at the end of the page. Which will simply find and replace URLs to links. Make sure you don't double up. Regex is your friend here.

XSLT substring and hash tag

Can someone tell me why this is not working?
Throughout my document I have several column breaks marked as follows: <cb ed="#S" n="45rb"/>
The hash tag is there to refer to another element where the source document is identified.
Now I want to display the column break in the following document. So that it looks like this:
|S45rb|. I thought I could use a simple substring function to get rid of the hash tag like so.
<xsl:template match="TU:cb">
<xsl:variable name="hashms"><xsl:value-of select="//TU:cb/#ed"/></xsl:variable>
<xsl:variable name="ms"><xsl:value-of select="substring($hashms,1,1)"/></xsl:variable>
<span>| <xsl:value-of select="$ms"/> <xsl:value-of select="//TU:cb/#n"/> |</span>
</xsl:template>
When I do it this way I get the following result: |#75ra|. Shouldn't the first 1 in the argument refer to the first character of the string and then the second 1 tell it to move over one character and leave me with the desired S? Instead I don't get the S but only the hash tag. Is there something about hash tags and strings I do not know?
Thanks for your help.
XSL is not 0 base, if you want to start at the second character (after the #), it should be 2 rather than 1.
http://www.w3schools.com/Xpath/xpath_functions.asp
substring($hashms,2,1) = S
You can also omit the length, which might be of benefit for extensibility later on. Especially if whatever comes after the # is the identifier, why limit your code?
substring($hashms,2) = S
substring('#S2',2) = S2

xsl strange behaviour using variables

I've stored a file's tree into $onto
<xsl:variable name="onto" select="document('file.xml')"/>
In some places I can use this variable as espected:
<xsl:copy-of select="$onto/rdf:RDF"/>
But I'm having trouble in other places, strange chars are written on output:
<xsl:element name="autor">
<xsl:attribute name="rdf:resource">
<xsl:text>#</xsl:text> <xsl:value-of select="$onto"/>
</xsl:attribute>
</xsl:element>
This is the beginig of the output I've got:
<autor rdf:resource="#
What I'm missing? What's wrong?
If that's to much for an attribute, what can I do?
Thank you
When <xsl:value-of> is applied to a tree fragment, it takes the text content of that tree. In your case, it looks like your XML file doesn't contain any text (other than whitespace) which isn't in an attribute value. I suspect that you mean to select the value of a particular attribute node within the document, e.g.:
<xsl:value-of select="$onto//foo/#bar"/>
(Without knowing the structure of your XML and what you're trying to select, I don't know what the real path would be.)

How do I format text in between xsl:text tags?

I have an xslt sheet with some text similar to below:
<xsl:text>I am some text, and I want to be bold</xsl:text>
I would like some text to be bold, but this doesn't work.
<xsl:text>I am some text, and I want to be <strong>bold<strong></xsl:text>
The deprecated b tag doesn't work either. How do I format text within an xsl:text tag?
Try this:
<fo:inline font-weight="bold"><xsl:text>Bold text</xsl:text></fo:inline>
XSL-FO Tutoria: Inline Text
Formatting
XSL-FO inline Object
You don't. xsl:text can only contain text nodes and <strong> is an element node, not a string that starts with less-than character; XSLT is about creating node trees, not markup. So, you have to do
<xsl:text>I am some text, and I want to be </xsl:text>
<strong>bold<strong>
<xsl:text> </xsl:text>
<xsl:text disable-output-escaping="yes">I want to be <strong>bold<strong> </xsl:text>
The answer for this depends on how much formatting is needed in the content and also where you get content from.
If you have less content and less formatting then you can use what jelovirt suggested
<xsl:text>I am some text, and I want to be </xsl:text>
<strong>bold<strong>
<xsl:text> </xsl:text>
However if your content has large formatting then what David Medinets suggests is better way to do it
<xsl:text disable-output-escaping="yes">
We have some instructions to print on UI. The set of instructions is huge and of course we read those from XML file.
In such cases the above method is easy to use and maintain too. That is because the content is provided by technical writers. They have no knowledge of XSL. They know using HTML tags and they can easily edit the XML file.
the correct way to use the strong tag is
<strong>This text is strong</strong>
not <strong> at the end
Here is the information reference: https://www.w3schools.com/html/html_formatting.asp