Setting a number as element name in XSLT 1.0 - xslt

In my xslt I have a variable 'number'. I want to use this value as an element's name in my final xml output. How can I achieve this?
XSLT
<input>
<xsl:variable name="number" value="658976"/>
<xsl:element name="{$number}">Hello</xsl:element>
</<input>
Expected Output
<input>
<658976>Hello</658976>
</input>

An XML element's name cannot start with a digit: https://www.w3.org/TR/2008/REC-xml-20081126/#NT-NameStartChar

Related

How to find smallest string in result tree fragment(RTF) containing two strings without using extension function e.g. node-set in xslt 1.0

I have two strings variables basically storing currency codes which can have values like USD or EUR or JPY etc.
Examples:
If variable boughtccy contains 'JPY' and variable soldccy contains 'USD' then it should return a string 'BOUGHTCCY' signifying that it is the variable named boughtccy actually contains the smallest currency.
Similarly, if variable boughtccy contains 'EUR' and variable soldccy contains 'AUD' then it should return a string 'SOLDCCY' signifying that it is the variable named soldccy actually contains the smallest currency.
I have written following code which works perfectly fine except for in Altova XMLSpy. I have a requirement that it should also work in XMLSpy.
Here is the code:
xsl:variable name="smallerccy">
<xsl:variable name="nodes">
<node>
<xsl:value-of select="$boughtccy"/>
</node>
<node>
<xsl:value-of select="$soldccy"/>
</node>
</xsl:variable>
<xsl:for-each select="common:node-set($nodes)/*">
<xsl:sort select="."/>
<xsl:choose>
<xsl:when test="position()=1 and .=$boughtccy">BOUGHTCCY</xsl:when>
<xsl:when test="position()=1 and .=$soldccy">SOLDCCY</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
How do I achieve this without using exslt:node-set() function? I cannot use xslt 2.0.
I believe the underlying problem you are having is that in XSLT 1.0 strings can only compared only for equality (or inequality), and so you can simply do <xsl:when test="$boughtccy > $soldccy">
In you particular case, where you are dealing with a finite number of strings, you could define a variable containing all possible currency codes, and use string handling to find one is first.
Try this XSLT (You would, of course, have to amend $AllCurrencies to have all possible currency codes).
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:variable name="AllCurrencies" select="'AUS|EUR|JPY|USD'" />
<xsl:param name="boughtccy" select="'JPY'" />
<xsl:param name="soldccy" select="'USD'" />
<xsl:template match="/">
<xsl:choose>
<xsl:when test="string-length(substring-before($AllCurrencies, $boughtccy)) < string-length(substring-before($AllCurrencies, $soldccy))">BOUGHTCCY</xsl:when>
<xsl:otherwise>SOLDCCY</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
I would write conditional logic, using system-property() and function-available(), that implements this in different ways for different processors:
if it's XSLT 2.0, use min(($boughtccy, $soldccy))
if it's XSLT 1.0 with a node-set extension, use the sorting technique that you're already using
otherwise give up. (There is no way to compare two strings for "<" in XSLT 1.0 other than creating a node-set and sorting it, and that requires the node-set extension).

XSLT and XPATH to find the correct element using data from sibling elements

I'm having trouble locating the correct syntax for finding the value of an element based on sibling element data.
Given that I have the following XML:
<files>
<file>
<location>location1.txt</location>
<metadata>
<foo>some value 1</foo>
</metadata>
</file>
<file>
<location>location2.txt</location>
<metadata>
<foo>some value 2</foo>
</metadata>
</file>
<file>
<location>location3.txt</location>
<metadata />
</file>
</files>
What is the correct XPATH expression to find the correct location value if I'm looking for only the location where file/metadata/foo = "some value 2"? I can't seem to find the right syntax to locate it if I'm dependent on data in a sibling, or the children of that sibling.
I've found a solution where I use xslt to iterate through the file elements, and find the appropriate value that way, but it's not very elegant.
<xsl:variable name="profileAlias">
<xsl:for-each select="files/file">
<xsl:if test="metadata/foo='some value 2'">
<xsl:value-of select="location">
</xsl:if>
</xsl:for-each>
</xsl:variable>
If you need to take one only value you can try this one, if this is elegent for you :D
<xsl:value-of select="files/file/location[following-sibling::metadata/foo/text()='some value 2']"/>
files/file/location - takes location attribute
[following-sibling::metadata/foo/ - which has next attribute metadata/foo/
text()='some value 2'] - with text equal 'some value 2'
Try
/files/file[metadata/foo='some value 2']/location

Xpath test if is numeric OR valid numeric expression

It is quite simple to find out if a node value is numeric by for example:
<xsl:if test="string(number(myNode)) != 'NaN'">
<!-- myNode is numeric -->
</xsl:if>
But, what if myNode contains a fraction or other valid numeric expression? What is the best way to find that out?
Example XML:
<data id="1">34</data>
<data id="2">52.3</data>
<data id="3">5/9</data>
<data id="4">10*20</data>
<data id="5">foo</data>
Example XSL:
<xsl:for-each select="//data">
<xsl:if test="string(number(.)) != 'NaN'">
<isNumeric><xsl:value-of select="#id"/></isNumeric>
</xsl:if>
</xsl:if>
Will generate the output:
<isNumeric>1</isNumeric>
<isNumeric>2</isNumeric>
But what is the easiest way to write the xpath expression (or xsl code) to generate the following output:
<isNumeric>1</isNumeric>
<isNumeric>2</isNumeric>
<isNumeric>3</isNumeric>
<isNumeric>4</isNumeric>
...since data id 3 and 4 also are valid numeric expressions.
It is ok to assume the node value does not contain any spaces as this is controlled by the schema used.
Assuming you don't need to validate your expressions so 4/0 or even 4/+/9 are OK then
<xsl:if test="translate(.,'0123456789.+-/* ','')=''">
<isNumeric><xsl:value-of select="#id"/></isNumeric>
</xsl:if>

display xml elements inside xml using xslt

Ia using XSLT 1.0 and I do have a XML while looks like this
<item name="note"><value><p>Add the &lt;bean&gt; tag pased below to the &lt;beans&gt; element in this file .... </value></item>
I want to display it like this in HTML
Add the <bean> tag passed below to the <beans> element in this file.
Note here that the <p> will be converted to a paragraph tag as I use disable-output-escaping= yes.
This is what I have in my xslt
<xsl:template match="item[#name='note']">
<xsl:value-of select="value" disable-output-escaping="yes" />
</xsl:template>
With this xslt it ignores the bean and beans xml and it does not get displayed in the page. How do I make sure to display it the way I want it?
The problem is that some of your entities have been "double escaped".
&lt;bean&gt; should be <bean>

how to make an element inside a variable

XSLT 1.0
I will need a variable with the following structure, basically I need to construct a variable which actually is a element. I know it looks silly but I need such thing because of the limitation of other stuff.
<xsl:variable name="options">
<xsl:element name="option">
<xsl:attribute name="value">
<xsl:text>test1</xsl:text>
</xsl:attribute>
<xsl:text>test1</xsl:text>
</xsl:element>
</xsl:variable>
Now the problem is, when I call it later in the template with
<xsl:value-of select="$options"/>
the output html only have test1 instead of what I want
<option>test1</option>
So it means the tag is missing. What's the right syntax to do this? Thanks in advance!
You need to make difference between <xsl:value-of> and <xsl:copy-of>
In XSLT 1.0 the <xsl:value-of> instruction creates a text node that contains the string value of the result of evaluating the XPath expression, specified in the select attribute. By definition, the string value of an element is the concatenation (in document order) of all of its descendent text nodes -- this is how you get the string "test1" output.
By contrast:
<xsl:copy-of>
outputs a copy of every node of the node-set that is selected by the XPath expression specified in the select attribute.
Therefore, in order to copy the complete contents of $options, you need to specify:
<xsl:copy-of select="$options" />
Here is a complete example:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vOptions">
<option value="test1">test1</option>
</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select="$vOptions"/>
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on any XML document (not used), the wanted, correct result is produced:
<option value="test1">test1</option>
try:
<xsl:copy-of select="$options" />