Replace text in XSL with conditional statements - xslt

I am working with XML files that are generated by a digital video camera. The camera allows the user to save all of the camera's settngs to an SD card so that the settings can be recalled or loaded into another camera. The XSL stylesheet I am writing will allow users to view the camera's settings, as saved to the SD card in a web browser.
While most of the values in the XML file -- as formatted by my stylesheet -- make sense to humans, some do not. What I would like to do is have the stylesheet display text that is based on the value in the XML file but more easily understood by humans.
My sample XML file may be viewed here: http://josephthomas.info/Alexa/Setup_120511_140322.xml
A few lines down the page you will see:
Color GAMMA-SxS Rec_Log
While "Rec_Log" is a value that the cameras understand, it is not a value that the camera's users will understand. What I would like for the stylesheet to do is to display "LogC" instead.
In the XML file this value is defined thusly:
<DteLut lowerLimit="0" upperLimit="2">Rec_Log</DteLut>
The XSL formatting the sample page for this value is:
<tr>
<td class="title_column">Color GAMMA-SxS</td><td><xsl:value-of select="Settings/Groups/Recording/DteLut"/>
</td>
</tr>
So what I hope to do is have "LogC" displayed on the page rather than Rec_Log.
It seems to me that the "when" conditional statement is the correct approach, but I am not familiar enough with the syntax to cause this to happen. There are other values in the XML file that want replacing but the above is a good example of my mission.

What you could do is make use of make use of template matching, to match the exceptions to what you want to change. Firstly, add the following template to your XSL
<xsl:template match="DteLut[. = 'Rec_Log']">
<xsl:text>LogC</xsl:text>
</xsl:template>
Then, instead of the following line
<xsl:value-of select="Settings/Groups/Recording/DteLut"/>
Do the following line
<xsl:apply-templates select="Settings/Groups/Recording/DteLut"/>
When the value of*DteLut* is "Rec_Log", then the custom template will be matched to output "LogC" instead. When there is not a match, the default behaviour will kick in which will be to just output the text value as-is.

I would use a data-driven approach. Have a mapping file that gives all the translations:
<translations>
<translate from="Rec_log" to="LogC"/>
<translate .../>
</translations>
then define a key:
<xsl:key name="trans" match="translate" use="#from"/>
and then change
<xsl:value-of select="Settings/Groups/Recording/DteLut"/>
to
<xsl:value-of select="key('trans', Settings/Groups/Recording/DteLut,
doc('translations.xml'))/#to"/>
if using XSLT 2.0, or
<xsl:variable name="val" select="Settings/Groups/Recording/DteLut"/>
<xsl:for-each select="document('translations.xml')">
<xsl:value-of select="key('trans', $val)/#to"/>
</xsl:for-each>
if you're stuck with 1.0.

Related

Can I include a variable inside a src attribute of an XSL-FO block?

We have 60-odd images that we want to include, and want to insert them into a doc using a variable name in the src attribute. Here is the code that currently isn't working:
Without XSL:-
<var name="Request.Data.Communication.AddressStructured.Sender.OrgId" type="string" />
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" xmlns:svg="http://www.w3.org/2000/svg" xmlns:th="http://www.thunderhead.com/XSL/Extensions" font-family="Frutiger 45 Light">
<fo:external-graphic content-height="30mm" content-width="100mm" src="cms:///Resources/Images/Request.Data.Communication.AddressStructured.Sender.OrgId.jpg" />
</fo:block>
With XSL:-
<xsl:block xmlns:xsl="http://www.w3.org/1999/XSL/Format" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" xmlns:svg="http://www.w3.org/2000/svg"
<xsl:var name="Request.Data.Communication.AddressStructured.Sender.OrgId" select="Request.Data.Communication.AddressStructured.Sender.OrgId"/>
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Transform" xmlns:fox="http://xmlgraphics.apache.org/fop/extensions" xmlns:svg="http://www.w3.org/2000/svg" <fo:external-graphic content-height="30mm" content-width="100mm" src="cms:///Resources/Images/${Request.Data.Communication.AddressStructured.Sender.OrgId}.jpg" />
</fo:block>
</xsl:block>
You might want {$Request.Data.Communication.AddressStructured.Sender.OrgId} rather than ${Request.Data.Communication.AddressStructured.Sender.OrgId}, otherwise read on...
Getting from your source XML to PDF output is a two-step process (unless, that is, you author documents directly in the XSL-FO vocabulary). The steps are:
An XSLT transformation transforms your XML into XML in the XSL-FO vocabulary that an XSL Formatter understands
An XSL Formatter formats the XSL-FO to make pages and outputs those pages as PDF, SVG, etc.
This graphic from the XSL 1.1 Recommendation (https://www.w3.org/TR/xsl11/#d0e147) tries to illustrate the process:
The XSLT stage has variables, but the XSL-FO stage does not. (You can write expressions for the value of (most) XSL-FO properties, but the expression language (see https://www.w3.org/TR/xsl11/#d0e5032) doesn't stretch to having variables.)
So, in your XSLT stylesheet, you would have something like:
{$Request.Data.Communication.AddressStructured.Sender.OrgId}.jpg
where:
$Request.Data.Communication.AddressStructured.Sender.OrgId is a variable (or parameter) reference. We don't have enough information to know how you'd define the variable.
{...} is an Attribute Value Template (AVT) that is used when you want to evaluate an expression to generate some or all of an attribute value.
The output from the XSLT stage would include the literal string resulting from evaluating the expression, and the XSL Formatter will use the actual URL to locate the image correctly.

disable-output-escaping twice in a DVWP using XSLT

I have a custom list. That custom list has a plain text milti-line field. In it the user will enter HTML, like <br>hi</br>;
I want to render that HTML in my DVWP using XSLT.
<xsl:value-of select="#Field_Name" disable-output-escaping="no" /> outputs <b>hi</b>
<xsl:value-of select="#Field_Name" disable-output-escaping="Yes" /> outputs <b>hi</b>
Anyway I can make it render the actual HTML? So I want it to output hi.
Change your custom field from Plain text to Rich text type because plain text assume <b>hi</b> as part of data. If you change your field type can see html formated text in your browser with same xslt code like hi.

How to select a property of a macro parameter in XSLT?

This is a very basic XSL question and I am just getting started with the topic in the context of Umbraco:
I've defined a macro with a XSLT file. The macro has a parameter of type 'ContentPicker'. What I want to do with the macro, is to render the picked content in a certain way. The relevant bit of my XSLT file is this:
<xsl:param name="source" select="/macro/BlogPostSource"/>
<xsl:template match="/">
<div>
<xsl:value-of select="$source/blogPostIntroduction"/>
</div>
I define a parameter, which is set to the parameter of the macro (this works). Now I simply want to render the property blogPostIntroduction which is a generic property on the picked content. This doesn't work. If I use
<xsl:value-of select="$source"/>
the ID of the content is rendered.
Question A: How do I select fields of the selected content?
Question B: Is my idea correct in general or am I missing a better way to do what I need, rather than using macros and XSLT?

Is there a way to remove all attributes from an XSLT attribute set when overriding that attr set?

I'm working with some third-party XSLT that makes heavy use of attribute sets for transforming XML to various forms of XSL:FO. Example:
notes.xsl:
<xsl:template match="note">
<fo:block xsl:use-attribute-sets="noteAttrs">
<!-- This is a pretty big template with lots of xsl:choose/xsl:if/etc. -->
</fo:block>
<xsl:template>
<xsl:attribute-set name="noteAttrs">
<xsl:attribute name="margin-left">10px</xsl:attribute>
<xsl:attribute name="margin-right">8px</xsl:attribute>
<xsl:attribute name="margin-top">5px</xsl:attribute>
<xsl:attribute name="font-size">10pt</xsl:attribute>
<!-- several other attributes -->
</xsl:attribute>
The idea is that I import this XSLT, redefining the attribute sets as I see fit. If I just need a different font size for a given .fo document...
<xsl:import href="notes.xsl"/>
<xsl:attribute-set name="noteAttrs">
<xsl:attribute name="font-size">12pt</xsl:attribute>
</xsl:attribute>
The problem is that sometimes I need to flat out remove attributes (i.e. so I inherit from the containing fo:block), or a given fo document is going to be so different that it would be easier to start fresh instead of merge my attribute set with the one from notes.xsl. Is there a way in XSLT 2.0 to do that without reproducing the entire template for note and specifying a different attribute set on the fo:block? I guess I'm looking to be able to do something like this:
<xsl:import href="notes.xsl"/>
<xsl:attribute-set name="noteAttrs" merge_with_imported_attr_set="false">
<xsl:attribute name="font-size">12pt</xsl:attribute>
</xsl:attribute>
I can't switch to an XSLT 3.0 processor immediately, but if there's something new in 3.0 that enables this, I'd love to know about it.
Thanks!
Attribute sets are not very widely used and to answer your question I had to look at the spec to refresh my memory. I don't think there is any way of achieving what you are wanting; you can't really override an attribute set in an importing stylesheet, you can only supplement it. In a well-designed XML vocabulary there is usually an attribute value you can set that is equivalent to omitting the attribute, but if that's not the case then you are stuck.

Getting the value of an attribute in an XML document using XSL

I'm trying to get the value of iWantToGetThis.jpg and put it into an <img> during my XSL transformation. This is how my xml is structures:
<article>
<info>
<mediaobject>
<imageobject>
<imagedata fileref='iWantToGetThis.jpg'>
Here's what I've come up with for the XSL:
<xsl:template name="user.header.content">
<xsl:stylesheet xmlns:d='http://docbook.org/ns/docbook'>
<img><xsl:attribute name="src">../icons/<xsl:value-of select='ancestor-or-self::d:article/info/mediaobject/imageobject/imagedata/#fileref' /></xsl:attribute></img>
</xsl:stylesheet>
</xsl:template>
The image is being added to the output, but the src attribute is set to "../icons/", so I'm assuming it's not finding the fileref attribute in the XML. This looks perfectly valid to me, so I'm not sure what I'm missing.
I am not sure how you can get anything back at all, because that does not look like a valid XSLT document (I would expect the error "Keyword xsl:stylesheet may not contain img.").
However, it may be you are just showing a fragment of the code. If this is the case, your issue may be that you have only specified the namespace for the article element, when you really need to specify it for all elements in your xpath. Try this
<xsl:value-of
select="ancestor-or-self::d:article/d:info/d:mediaobject/d:imageobject/d:imagedata/#fileref"/>
Another possible problem may be because you are using the 'ancestor-or-self' xpath axis to find the attribute. This would only work if your current context was already on the article element, or one of its descendants.
As a side note, you can simplify the code by making use of Attribute Value Templates here
<img src="../icons/{ancestor-or-self::d:article/d:info/d:mediaobject/d:imageobject/d:imagedata/#fileref}" />