How to use an xsl variable in a javascript block - xslt

I am trying to use an xsl variable in a javascript block in my xslt file and I am at my wit's end.
Here is the XSLT (edited for public consumption):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="a">
<xsl:variable name="myVar" select="xpath to the node"/>
<script type='text/javascript'>
googletag.cmd.push(function() {
...
googletag.pubads().setTargeting('label', '<xsl:value-of select="$myVar"/>');
googletag.enableServices();
});
</script>
</xsl:template>
</xsl:stylesheet>
If I transform the XML in Oxygen, this code works fine. But when I run it through my servlet, which uses javax.xml.transform.Transformer.transform(Source xmlSource, Result outputTarget) throws TransformerException, I get this:
googletag.pubads().setTargeting('label', ' ');
Can anyone suggest a possible reason for this discrepancy between Oxygen and my servlet?

Try this instead as contents of your variable:
<xsl:variable name="myVar" select="'xpath to the node'"/>
This ensures the contents is seen as a literal string. Possibly Oxygen is forgiving enough to ignore it and your Java is (correctly) not -- it's an error, because inside the quoted string you should put an expression.
The outer double quotes do not take part in forming the expression, only what's inside. That way you can express either the string '1+2' or the sum 1+2 in a variable.

Related

Regex applied to Replace function on XSLT 3 not working

I believe this is a simple problem, I'm trying to apply a Regex to my replace method in a variable in XSLT 3 (I'm also using Saxon (latest version)). I know it is possible to use replace with a regex but it seems that the regex I'm trying to use is wrong, it works in Java but not there on XSLT.
Here is my variable with the replace method:
<xsl:variable name="namePrefix" select="replace(#name, '/(.*_[^_]+)/')" />
I want this variable namePrefix to return me an specific part of the name of my Node (found under the attribute #name), here is an Name Example:
ALBA_MASTER_FIX_Test
I want this regex and replace methode to return to my variable everything before the last _.
I would like to know wheter I'm applying the regex correctly? Or if I should do it in a different way or use a different regex. Thx :)
everything before the last _.
I believe that could be simply:
replace(#name, '_[^_]*$', '')
Alternatively, you could use something like:
<xsl:value-of select="tokenize(#name, '_')[position() lt last()]" separator="_"/>
This works in the very useful xslt3fiddle based upon SaxonJS:
replace(#name, '(.*)_(.*)', '$1')
Can see used in this stylesheet
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all">
<xsl:output method="xml" indent="yes" />
<xsl:variable name="inputElement" as="element()" >
<input name="ALBA_MASTER_FIX_Test" />
</xsl:variable>
<xsl:template name="xsl:initial-template">
<output value="{replace($inputElement/#name, '(.*)_(.*)', '$1')}" />
</xsl:template>
</xsl:stylesheet>
with output
<output value="ALBA_MASTER_FIX"/>

exsl:document - trying to generate output file

I have this code so far: - now updated with different code
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:output method="xml"/>
<xsl:variable name="emailPID" select="attr[#tag='00100020']"/>
<xsl:variable name="emailPName" select="attr[#tag='00100010']"/>
<!-- overwritten by application with actual values -->
<xsl:param name="calling" select="'SAMPLE_MOD'"/>
<xsl:param name="called" select="'SERVER1'"/>
<xsl:param name="date" select="'20051206'"/>
<xsl:param name="time" select="'115600.000'"/>
<xsl:template match="/dataset">
<exsl:document href="file:///c|/apps/foo.txt">
<xsl:copy-of select="$emailPID"/>
<xsl:copy-of select="$emailPName"/>
</exsl:document>
</xsl:template>
</xsl:stylesheet>
The transformer doesn't throw any errors that I see, but I cannot see the "c:\apps\foo.txt" file I am expecting either. Is there some formatting wrong here or am I leaving something out?
thank you for looking
The processor should throw an error when it sees
extension-element-prefixes="exslt"
because the prefix "exslt" has not been declared. Perhaps you meant "exsl". At present, "exsl" is not declared as an extension namespace, therefore "exsl:document" is a simple literal result element rather than an instruction.
The href attribute of an exsl:document needs to be a valid URI. The XSLT engine is probably confusing the part before the colon (i.e. c) as a URI scheme, not part of the path.
If you are using an absolute address for the filesystem, include the file: URI scheme:
<exsl:document href="file:///c:\apps\foo.txt">
The drive colon ad slashes may cause problems on non-windows platforms so you can instead try:
<exsl:document href="file:///c|/apps/foo.txt">

Type of Amazon xml response breaks php xsl

Since Amazon shut off it's xslt support, I wanted to move it to my own server using php5's xsl. My output needs to be in a text format for my JS to process it for a web page. My problem is Amazon's xml response (very abbreviated) looks like this
<?xml version="1.0" ?>
<ItemLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
/............./
</ItemLookupResponse>
My problem is that my xsl stylesheet works fine as long as I remove the xmlns="http://...". What is needed in a xsl style to have it bypass or just ignore that ?
All the nodes I need are well inside that outer one.
Here is the xslt:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="CallBack" select="'amzJSONCallback'"/>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of select="$CallBack"/>
<xsl:text>( { "Item" : </xsl:text><xsl:apply-templates/><xsl:text> } ) </xsl:text>
</xsl:template>
<xsl:template match="OperationRequest"></xsl:template>
<xsl:template match="Request"></xsl:template>
<xsl:template match="Items">
<xsl:apply-templates select="Item"/>
</xsl:template>
<xsl:template match="Item">
<xsl:text> {</xsl:text>
<xsl:text>"title":"</xsl:text><xsl:apply-templates select="ItemAttributes/Title"/><xsl:text>",</xsl:text>
<xsl:text>"author":"</xsl:text><xsl:apply-templates select="ItemAttributes/Author"/><xsl:text>",</xsl:text>
<xsl:text>"pubbdate":"</xsl:text><xsl:apply-templates select="ItemAttributes/PublicationDate"/><xsl:text>"</xsl:text>
<xsl:text>} </xsl:text>
</xsl:template>
</xsl:stylesheet>
You should probably learn how XML namespaces work. In a nutshell, you have to define a namespace prefix in your XSL file like this:
<xsl:stylesheet ... xmlns:awse="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
Then, you have to use qualified names to match and select elements under that namespace:
<xsl:template match="awse:ItemLookupResponse">
(With XSLT 2.0, you can define a default namespace. But since you're using PHP, you're probably limited to XSLT 1.0.)
It looks like nwellnhof is correct. I was using the wrong namespace in my testing. All I did was add:
<xsl:stylesheet ... xmlns:aws="http://webservices.amazon.com/AWSECommerceService/2011-08-01">
Then the elements look like
<xsl:template match="aws:ItemLookupResponse">
Now the conversion works perfectly. I don't know why it didn't work the first time I tried it.

Escaping Double Quotes, Space and Allowing for an Extra Forward Slash

I have XML
<?xml version="1.0" encoding="UTF-8"?>
<icestats>
<stats_connections>0</stats_connections>
<source mount="/live">
<bitrate>Some data</bitrate>
<server_description>This is what I want to return</server_description>
</source>
</icestats>
And I have XSL
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:copy-of select="/icestats/source mount="/live"/server_description/node()" />
</xsl:template>
</xsl:stylesheet>
I want the output
This is what I want to return
If I remove the double quotes, space and forward slash from the source it works, but I haven't been able to successfully escape the non standard characters yet using suggested methods in other posts.
For clarity, below is the solution thanks to Lego Stormtroopr
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<xsl:copy-of select="/icestats/source[#mount='/live']/server_description/node()" />
</xsl:template>
</xsl:stylesheet>
There are a couple of issues you will need to resolve before your processor will produce the output you're looking for.
1) Your XML input must be made well-formed. The closing tag of the source element should not include the mount attribute that is specified on the opening tag.
<source mount="/live">
...
</source>
2) The XPath on your xsl:copy-of element must be made valid. The syntax for an XPath expression is (fortunately) not like the syntax for XML elements and attributes. Specifying which source element to match is done by predicating on an attribute value, like you have done, except that you need to use square brackets:
/icestats/source[#mount="/live"]/server_description
In order to use this XPath expression in an XSLT select statement, you will need to make sure that you enclose the entire select attribute value with one type of quotes, and use the other type of quotes within the attribute value, e.g.:
<xsl:value-of select="/icestats/source[#mount='/live']/server_description" />
With This input
<?xml version="1.0" encoding="UTF-8"?>
<icestats>
<stats_connections>0</stats_connections>
<source mount="/live">
<bitrate>Some data</bitrate>
<server_description>This is what I want to return</server_description>
</source>
</icestats>
and this stylesheet
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of select="/icestats/source[#mount='/live']/server_description" />
</xsl:template>
</xsl:stylesheet>
I get the following line of text from xsltproc and saxon:
This is what I want to return
The xsl:value-of element will return the string value of an element (here, that one text node). If you actually wanted the server_description element, then you can use xsl:copy-of to get the whole thing, tags and all. (You would have to update xsl:output as well.)
It looks like you are doing a select based on the attribute, so you just need to properly capture the attribute in the XPath. The quotes you use in the document and the XPath don't need to match, so you can switch them to single quotes ('):
<xsl:copy-of select="/icestats/source[#mount='/live']/server_description/node()" />
(Edited to correct the the missing / from the mount attribute.)
Also, your original document isn't valid XML, as XML doesn't allow attributes in the closing tag.
I think all you need to do is escape the quotes in the attribute string with ":
<xsl:copy-of select="/icestats/source mount="/live"/server_description/node()" />

Using Xsl:value-of is converting & in url into &

I have a xml something likethis
<root>
<testxml>
<details name="test" url="http://www.test.com/test.aspx?val=100&val2=200" />
</testxml>
<root>
When i transform this xml using xslt to another xml
<xsl:output method="html" indent="yes" encoding="UTF-8" />
<xsl:template match="root/testxml/details">
<convert>
<xsl:attribute name="url">
<xsl:value-of select="#url"/>
</xsl:attribute>
</convert>
I get the result output as this
<convert url="http://www.test.com/test.aspx?val=100&val2=200">
instead of
<convert url="http://www.test.com/test.aspx?val=100&val2=200">
issue here is: & in url is getting changed to & amp; how can i avoid this ,i want & in url as &.(not & amp;)
i tried <xsl:value-of disable-output-escaping="yes" select="#url" />
also but of not use.
could anyone please help me in this..
I get the result output as this
instead of
issue here is: & in url is getting
changed to & amp;
There is no issue and the URL is not changed at all:
To verify this use a transformation like this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*">
<xsl:value-of select="#url"/>
</xsl:template>
</xsl:stylesheet>
when this transformation is applied on the following XML document:
<convert url="http://www.test.com/test.aspx?val=100&val2=200"/>
The result is:
http://www.test.com/test.aspx?val=100&val2=200
So, the URL hasn't been changed in any way and there is still only a single & character in it.
What you observe is the mandatory escaping of some special characters (typically < and &) in XML, as dictated by the XML Spec.
The escaping of some special characters never alters the content of the string that is escaped -- only how it looks like when it is a part of an XML document.
how can i avoid this ,i want & in url
as &.(not & amp;)
You cannot, and as shown above, there is nothing to avoid.
& has to be escaped as & in a URL in an XML document. You can't have an unescaped ampersand like that.
Dimitre is quite correct - an ampersand in XML must always be escaped, and it's not clear why you're trying so hard to prevent it.
I'm puzzled though - you say you're generating XML, but you use the HTML output method, but you are generating a <convert> element which isn't defined in HTML. So I fear you are a little confused by something.