My XSLT is shown below.
aic is a namespace.
What is cstyle?
is it a built-in XSLT element/function?
Or an element within the expected input xml?
<xsl:stylesheet exclude-result-prefixes="aic"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:aic="http://ns.adobe.com/AdobeInCopy/2.0/" >
<xsl:template match="/">
</xsl:template>
<xsl:template match="aic:cstyle[contains(#name,'bold')]">
</xsl:template>
</xsl:stylesheet>
It is an element within the expected input XML. The XPaths in an XSLT's match attributes are generally applied to contents from the input XML.
Exactly as in my answer to your previous question, aic:cstyle is a selector that matches elements whose local name is cstyle and whose namespace URI is http://ns.adobe.com/AdobeInCopy/2.0/ (the URI bound to the aic prefix in the xsl:stylesheet element). Thus
<xsl:template match="aic:cstyle[contains(#name,'bold')]">
is a template that will apply to any {http://ns.adobe.com/AdobeInCopy/2.0/}cstyle element that has a name attribute that contains the substring bold. (So, to answer your question directly: the expression in question will match elements in the input streams for which the stylesheet was written.)
As with any new programming language, I would strongly recommend that you find a decent tutorial and work through that to get comfortable with the syntax and idioms of the language through simple examples before you start trying to decode a large and complex XSLT that you've inherited from elsewhere.
Related
Relating to this question, is it possible to use variables inside xsl:key? I want to do smth like this:
<xsl:key name="ChargesKey" match="$ChargesForDisplay/charge" use="Name"/>
I'm using XSLT 1.0 with ASP.Net
I believe I can safely assume that you are referring to dynamically-generated node-set variables (as opposed to those selected from the source DOM, which are trivial), and yes it is possible to perform a key-match on the contents of a dynamically generated node-set variable (as I demonstrate for this question).
Assuming you have a variable like this:
<xsl:variable name="ChargesForDisplay">
<charge>
<Name>Name1</Name>
</charge>
<charge>
<Name>Name2</Name>
</charge>
<charge>
<Name>Name1</Name>
</charge>
<charge>
<Name>Name3</Name>
</charge>
</xsl:variable>
You would define the key like this:
<xsl:key name="ChargesKey" match="charge" use="Name"/>
And then you can apply it like this:
<xsl:template match="/">
<xsl:apply-templates select="msxsl:node-set($ChargesForDisplay)" />
</xsl:template>
<xsl:template
match="charge[generate-id(.)=generate-id(key('ChargesKey',Name)[1])]">
<xsl:variable name="matchingItems" select="key('ChargesKey', Name)" />
...
</xsl:template>
Of course, if the variable contains a selection of nodes from the source XML DOM, then it's just the same approach, except you don't need to use msxsl:node-set().
I suspect that having a key on a node-name that's also present in the source XML document or multiple dynamically-generated node-set variables may cause grouping to produce unexpected results(because the key() function would locate nodes from both the variable and the source document). For this reason, I'd suggest defining keys on nodes that would only be present in one particular variable and nowhere else.
The match attribute of xsl:key must be a valid pattern and $x/y is not a valid pattern. So, the answer is no. Now tell us what you are trying to achieve and we can help you achieve it. (JLRishe makes some wild guesses, which s/he calls "wild assumptions", and which may well be right; but I don't know where the guesses come from).
I am trying this in an XQuery (assume that doc('input:instance') does indeed return a valid XML document) which is generated using XSLT
let $a:= <xsl:text>"<xsl:copy-of select="doc('input:instance')//A" />"</xsl:text>
let $p := <xsl:text>"<xsl:copy-of select="doc('input:instance')//P" />"</xsl:text>
let $r := <xsl:text>"<xsl:copy-of select="doc('input:instance')//R" />"</xsl:text>
But I get the error:
xsl:text must not contain child elements
How do I retrieve XML results using the XPath in xsl:copy-of and then encode the special characters received in the result while formatting the result as string? I would be happy to use CDATA section if that's possible (if I do that instead of xsl:text above, xsl:copy-of is not evaluated since it becomes part of CDATA section).
Obviously I am a newcomer to XSL...
What you need here is the ability to serialize an XML document (here the document returned by doc()) using the XML serialization, into a string.
Various XQuery implementation have extension functions for this purpose. For example, if you are using Saxon:
saxon:serialize(document, 'xml')
This has nothing to do with XQuery (you could be building the XSLT stylesheet with any language, even XSLT itslef!).
From http://www.w3.org/TR/xslt20/#xsl-text
<!-- Category: instruction -->
<xsl:text
[disable-output-escaping]? = "yes" | "no">
<!-- Content: #PCDATA -->
</xsl:text>
[...] The content of the xsl:text
element is a single text node whose
value forms the string value of the
new text node.
I am using some code to subtract one date from another using XSLT 2.0:
<xsl:template match="moveInDate">
<xsl:value-of select="current-date() - xs:date(.)"/>
</xsl:template>
This works, however it leaves me with an answer of P2243D, which I assume corresponds to a "Period of 2243 Days" (which is correct in terms of the math).
Since I only need the number of days, not the P and the D, I know I could use substring or something similar, but as a newbie to XSLT, I'm curious if there is a better, more elegant way to do this than simple string manipulation.
You could simply use fn:days-from-duration() to get the duration as a xs:integer:
days-from-duration($arg as xs:duration?) as xs:integer?
Returns an xs:integer representing the days component in the canonical lexical representation of the value of $arg. The result may be negative.
See the XQuery 1.0 and XPath 2.0 Functions and Operators specification for more information.
In your case:
<xsl:template match="moveInDate">
<xsl:value-of select="days-from-duration(current-date() - xs:date(.))"/>
</xsl:template>
Hope this helps!
EDIT: You could also do it the way you say, with substring processing. But as you point out, it's not prefered. If you for some reason would like to do something similar you need to think of the data types. The result of current-date() - xs:date(.) is returned as xs:duration which cannot be processed by the substring functions without being casted:
<xsl:template match="moveInDate">
<xsl:variable name="dur" select="(current-date() - xs:date(.)) cast as xs:string"/>
<xsl:value-of select="substring-before(substring-after($dur, 'P'), 'D')"/>
</xsl:template>
I have an XSLT function that takes a regular expression as a parameter but the XSLT parser does not like it.
Here is the code:
<xsl:value-of select='ns:RegexReplace($variable, "", "style=\"\w+\:\s\w+;\"")' disable-output-escaping='yes' />
I found this:
http://www.xml.com/pub/a/2003/06/04/tr.html <-- but it is using what I am and seems to work (for them). Do I just have a rubbish parser??
Is there any way of doing this?
Or, a way of forcing an element to ignore inline style via a CSS trick?
You seem to be trying to include quotes in a quote-delimited XPath string literal by escaping them with a backslash. That does not work.
In XPath 1.0 (XSLT 1), there is no nice way to do this. You may need to resort to tricks like defining a variable which holds a single quote character and using the concat function to create your string:
<xsl:variable name='quot' select="'"'"/>
<xsl:value-of select='concat("a string with a quote ", $quot, " character")'/>
In XPath 2.0 (XSLT 2), you can escape a quote with another quote:
<xsl:value-of select='"a string with a quote "" character"'/>
It occurs to me that you may be trying to remove style attributes. If that is the case, then string replacement is not going to help you.
You can remove style attributes for example by writing a template which matches them and outputs nothing:
<xsl:template match="#style"/>
I use XSLT to transform an XML document which I then load on to a ASP.NET website. However, if the XML contains '<' characters, the XML becomes malformed.
<title><b> < left arrows <b></title>
If I use disable-output-escaping="yes", the XML cannot be loaded and I get the error "Name cannot begin with the '' character".
If I do not disable output escaping the escaped characters are disregarded and the text appears as it is:
<title><b> < left arrows <b></title>
I want the bold tags to work, but I also want to escape the '<' character. Ideally
<b>< left arrows</b>
is what I want to achieve. Is there any solution for this?
The XML should contain the escaped sequence for the less than sign (<), not the literal < character. The XML is malformed and any XML parser must reject it.
In XSLT you could generate that sequence like this:
<xsl:text><<xsl:text>
From what I understand, the input contains HTML and literal < characters. In that case, disable-output-escaping="yes" will preserve the HTML tags but produce invalid XML and setting it to no means the HTML tags will be escaped.
What you need to do is to leave set disable-output-escaping="no" (which is the default, you don't actually have to add that) and add a XSLT rule that will copy the HTML tags. For instance:
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="#*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
I came up with a solution and was triggered by the last answer by Josh. Thanks Josh. I tried to used the match template, however I had a problem as the html tags are placed within cdata, so I had difficulties doing a match. There might be a way to do it, but I gave up on that.
What I did was to do a test="contain($text, $replace)" where the $replace is the '<' character and on top of that, I also added a condition to test if the substring after the '<' is a relevant html tag such that it is actually a <b> or </b>. So if it's just a '<' character not belonging to any html tags, I will convert '<' to ampersand, <. Basically that solved my problem. Hope this is useful to anyone who encounter the same problem as me.