xsl text and normal string - xslt

What is the differnce between
<xsl:param name="abc">123</xsl:param>
<xsl:param name="def"><xsl:text>123</xsl:text></xsl:param>
They both work same but is there some difference between the two.

<xsl:text> will allow you to manipulate the text (escape as well as white space):
<xsl:text disable-output-escaping="yes|no">
From http://msdn.microsoft.com/en-us/library/ms256107(v=vs.110).aspx:
In a style sheet, text can be generated to the literal result tree
with or without <xsl:text>. However, with this element you can exert
some control over the white space created by the style sheet. For
example, to make your style sheet more readable, you might want to
write one element per line in a template, and indent some lines. Doing
so introduces white space as part of the template rule. This might or
might not be a desired effect of the transformation. Sometimes you
might want to introduce a white space character to separate two data
values. You can use an <xsl:text> element to accomplish this. White
space enclosed within <xsl:text> is output to the result tree.

The main reason for using <xsl:text> is that whitespace arount text XSLT stylesheets is normally discarded/stripped (http://www.w3.org/TR/xslt#strip). Text enclosed in <xsl:text> is the exception to that rule. So if you want to explicitly output spaces, tabs, or newlines you may need to use <xsl:text>
<xsl:text> also allows case-by-case control over the output escaping mode. That's less frequently used; disabling output escaping is usually the wrong solution unless you're generating non-XML/non-HTML output.
[Apologies for the confusion, now corrected above. I just noticed that I had indeed been looking at a Working Draft of XSLT 1.0, not the final RECcomendation. Mea culpa, mea culpa, mea maxima culpa.]

Related

Duplicate line and replace string

I have an XML file that contains more than 10,000 items. Each item contains a line like this.
<g:id><![CDATA[FBM00101816_BLACK-L]]></g:id>
For each item I need to add another line below like this:
<sku><![CDATA[FBM00101816]]></sku>
So I need to duplicate each g:id line, replace the g:id with sku and trim the value to delete all characters after the underscore (including it). The final result would be like this:
<g:id><![CDATA[FBM00101816_BLACK-L]]></g:id>
<sku><![CDATA[FBM00101816]]></sku>
Any ideas how to accomplish this?
Thanks in advance.
In XSLT, it's
<xsl:template match="g:id">
<xsl:copy-of select="."/>
<sku><xsl:value-of select="substring-before(., '_')"/></sku>
</xsl:template>
Or using Saxon's Gizmo (https://www.saxonica.com/documentation11/index.html#!gizmo) it's
follow //g:id with <sku>{substring-before(., '_')}</sku>
Don't try to do this sort of thing in a text editor (or any other tool that doesn't involve a real XML parser) unless it's a one-off. Your code will be too sensitive to trivial variations in the way the source XML is written and will almost inevitably have bugs - which might not matter for a one-off, but do matter if it's going to be used repeatedly over a period of time.
Note also, the CDATA tags in your input (and output) are a waste of space. CDATA tags have no significance unless the element content includes special characters like < and &, which isn't the case in your examples.
Okay, so after commenting, I couldn't help myself. This seemed to do what you asked for.
find: <g:id><!\[CDATA\[([^\_]+)?(.+)?\]></g:id>
replace: $0\n<sku><![CDATA[$1]></sku>
I don't have BBEdit, but this is what it looked like in Textmate:

XSLT engine removing whitespace from <xsl:text> element in text output

I have a transformation that outputs a fixed length output, so where data is "missing" I pad the data with spaces.
so using
<xsl:output method="text" encoding="ISO-8859-1"/>
and then using things like
<xsl:text> </xsl:text>
whenever I need to pad for missing data.
This works very nicely in my dev environment (using visual studio).
but when I deploy it to another machine (which also uses MS XSLT engine, but with unknown parameters, allegedly 6.0), some of my whitespace gets "removed" and my data gets misalligned.
If I replace the above with things like
<xsl:text> </xsl:text>
then that doesnt get stripped.
this also works
<xsl:text xml:space="preserve"> </xsl:text>
Is there a way to get the XSLT to 'preserve' standard spaces in the "text" elements globally?
(the transformation is quite big and I don't want to have to go through replacing every space with , plus it worries me that its not doing 'exactly' what I'm asking it to do)
(I've looked at other questions on this, which is where I got the from, but I'd like to turn the XSLT behaviour OFF)

Prevent Narrow Non-Breaking Space (n-nbsp) in XSLT output

I have an XSLT transform that puts   into my output. That is a narrow-non breaking space. Here is one section that results in nnbsp:
<span>
<xsl:text>§ </xsl:text>
<xsl:value-of select="$firstsection"/>
<xsl:text> to </xsl:text>
<xsl:value-of select="$lastsection"/>
</span>
The nnbsp in this case, comes in after the § and after the text to.
<span>§ 1 to 8</span>
(interestingly, the space before the to turns out to be a regular full size space)
This occurs in my UTF-8 encoded output, as well as iso-8859-1 (latin1).
How can I avoid the nnbsp? While the narrow space is visually more appropriate, it doesn't work for all the devices that will read this document. I need a plain vanilla blank space.
Is there a transform setting? I use Saxon 9 at the command line.
Should I do a another transform.. using a replace template to replace the nnbsp?
Should I re-do my templates like the one above? Example, if I did a concat() would that be a better coding practice?
UPDATE: For those who may find this question someday... as suggested by Michael Kay, I researched the issue further. Indeed, it turns out narrow-NBSP were in the source XML files (and bled into my templates via cut/paste). I did not know this, and it was hard to discover (hat tip to gVim hex view). The narrows don't exactly jump out at you in a GUI editor. I have no control over production of the source XML, so I had to find a way to 'deal with it.' Eric's answer below turned out to be my preferred way to scrub the narrow-nbsp. SED editing was (and is) an another option to consider, but I like keeping my production in XSLT when possible. So Eric's suggestion has worked well for me.
You could use the translate() function to replace your nnbsp by something else, but since you are using Saxon 9 you can rely on XSLT 2.0 features and use a character map which will do that kind of things automatically for you, for instance (assuming that you want to replace them by a non breaking space:
<xsl:output use-character-maps="nnbsp"/>
<xsl:character-map name="nnbsp">
<xsl:output-character character=" " string=" "/>
</xsl:character-map>
Eric
The narrow non-breaking space is coming from somewhere: either the source document or the stylesheet. It's not being magically injected by the XSLT processor. If it's in the stylesheet, then get rid of it. If it's in the source document, then transform it away, for example by use of the translate() function.
In fact, pasting your code fragment into a text editor and looking at it in hex, I see that the 202F characters are right there in your code. I don't know how you got them into your stylesheet, but you should (a) remove them, and (b) work out how it happened so it doesn't happen again.

FOP warning:line 1 of a paragraph overflows the available area by more than 50 points

Just to make sure I would like to share my understanding of FOP vre 1.0 with you,
FOP uses a automated line breaking algorithm i.e when data overflows the width of a table cell,FOP looks for white space in the data and if it finds a white space,then it wraps the data that overflows from the nearest white space into next line of that cell.
But what if the data don't has a white space,then then FOP is not able to wrap data.
This is the problem I'm facing.
I write this code.
<fo:table-cell border="solid">
<fo:block hyphenate="true" language="en" wrap-option="wrap">
<xsl:value-of select="welcomeMsg"></xsl:value-of>
</fo:block>
</fo:table-cell>
but it overflows from table cell,instead of wraping because the welcomeMsg is a long string with no white spaces in between.I need the welcomeMsg to be wrapped inside table cell.
Apache FOP implements the Unicode UAX #14 algorithm for line breaking. So, if a word (or loooong number) cannot be broken and therefore overflows a table-cell, it's because of that algorithm. The usual work-around is to insert zero-width spaces (​) into fields that you know could cause overflows. This can easily be done via XSLT. See also: How to force wrap on table entries

XSLT: keeping whitespaces when copying attributes

I'm trying to sort Microsoft Visual Studio's vcproj so that a diff would show something meaningful after e.g. deleting a file from a project. Besides the sorting, I want to keep everything intact, including whitespaces. The input looks like
space<File
spacespaceRelativePath="filename"
spacespace>
...
The xslt fragment below can add the spaces around elements, but I can't find out how to deal with those around attributes, so my output looks like
space<File RelativePath="filename">
xslt I use for the msxsl 4.0 processor:
<xsl:for-each select="File">
<xsl:sort select="#RelativePath"/>
<xsl:value-of select="preceding-sibling::text()[1]"/>
<xsl:copy>
<xsl:for-each select="text()|#*">
<xsl:copy/>
</xsl:for-each>
Those spaces are always insignificant in XML, and I believe that there is no option to control this behavior in a general way for any XML/XSLT library.
XSLT works on a tree representation of the input XML. Many of the irrelevant detail of the original XML has been abstracted away in this tree - for example the order of attributes, insignificant whitespace between attributes, or the distinction between " and ' as an attribute delimiter. I can't see any conceivable reason for wanting to write a program that treats these distinctions as significant.