Using xml-to-json. "Inner XML/XHTML" should go in a json string value field - json

I'm using Saxon Home Edition to convert XML to JSON:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/">
<xsl:variable name="xmljson">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<string key="name">Some name</string>
<string key="description">A nice description</string>
</map>
</xsl:variable>
<xsl:value-of select="xml-to-json($xmljson)" />
</xsl:template>
</xsl:stylesheet>
Produces the desired output:
{"name":"Some name","description":"A nice description"}
The description field contains arbitrary complex xhtml. The template rule does not work with the following description field:
<string key="description">A <strong>nice</strong> description</string>
Error message:
xml-to-json: unknown element <strong>
Enclosing the description in a CDATA section does work:
<string key="description"><![CDATA[A <strong>nice</strong> description]]></string>
Desired output:
{"name":"Some name","description":"A <strong>nice<\/strong> description"}
Problem/Question
The content of the description field is the result of a transformation. So with and withou CDATA fails. This will not work:
<string key="description"><xsl:apply-template select="description" /></string>
Neither this:
<string key="description"><![CDATA[<xsl:apply-template select="description" />]]></string>

Use the serialize() function to produce escaped XML markup as text.
<xsl:variable name="options" as="element()">
<output:serialization-parameters xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization">
<output:omit-xml-declaration value="yes"/>
</output:serialization-parameters>
</xsl:variable>
<xsl:variable name="xmljson" as="element()">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<string key="name">Some name</string>
<string key="description"><xsl:value-of select="serialize(description, $options)"/></string>
</map>
</xsl:variable>

I came up with the following quick hack. Have to check this tomorrow again, kind of tired now...t
Edit: This is a horrible hack! The template rule does not treat special characters. Please read the comments below.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:template match="/">
<xsl:variable name="doc">
<description>A <strong class="red">nice</strong> description</description>
</xsl:variable>
<xsl:variable name="xmljson">
<map xmlns="http://www.w3.org/2005/xpath-functions">
<string key="description"><xsl:apply-templates select="$doc/description/text()|$doc/description/*" /></string>
</map>
</xsl:variable>
<xsl:value-of select="xml-to-json($xmljson)" />
</xsl:template>
<xsl:template match="*">
<!-- opening tag -->
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<!-- attribute nodes -->
<xsl:apply-templates select="#*"/>
<xsl:text>></xsl:text>
<xsl:apply-templates/>
<!-- closing tag -->
<xsl:text><</xsl:text>
<xsl:text>/</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
</xsl:template>
<xsl:template match="#*">
<xsl:text> </xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>="</xsl:text>
<xsl:value-of select="." />
<xsl:text>"</xsl:text>
</xsl:template>
</xsl:stylesheet>
Produces the desired output:
{"description":"A <strong class=\"red\">nice<\/strong> description"}

Related

XSLT Comma separating list, without grouping

I'm trying to convert the following XML document:
<method>
<desc_signature>
<desc_name>
Some method name
</desc_name>
</desc_signature>
<desc_content>
<paragraph>Paragraph1</paragraph>
<image>Image1</image>
<paragraph>Paragraph2</paragraph>
<literal_block>Codesnippet1</literal_block>
<image>Image2</image>
<paragraph>Paragraph3</paragraph>
<image>Image3</image>
<literal_block>Codesnippet2</literal_block>
</desc_content>
</method>
To the following JSON format:
{
"title":"Some method name",
"elements":[
"Paragraph1",
"Paragraph2",
"Codesnippet1",
"Paragraph3",
"Codesnippet2",
]
}
What I basically want to achieve, is to comma separate a list, but only include paragraph and literal_blocks, and still keeping the original order.
My first attempt was an XSLT that looks like this, with this union selector:
<xsl:for-each select="desc_content/paragraph|desc_content/literal_block">
Like this:
<!-- Method template -->
<xsl:template name="method">
{
"title":"<xsl:value-of select="normalize-space(desc_signature/desc_name)" />",
"elements":[
<xsl:for-each select="desc_content/paragraph|desc_content/literal_block">
<xsl:choose>
<xsl:when test="self::paragraph">
<xsl:call-template name="paragraph"/>
</xsl:when>
<xsl:when test="self::literal_block">
<xsl:call-template name="code"/>
</xsl:when>
</xsl:choose>
<xsl:if test="position()!=last()">
<xsl:text>,</xsl:text>
</xsl:if>
</xsl:for-each>
]
}
</xsl:template>
However, it seems like it is grouping paragraphs and then literal_blocks:
{
"title":"Some method name",
"elements":[
"Paragraph1",
"Paragraph2",
"Paragraph3",
"Codesnippet1",
"Codesnippet2",
]
}
Another approach was to select all:
<xsl:for-each select="desc_content/*">
That, however, yields too many commas, as position() accounts for all elements, even if not used:
{
"title":"Some method name",
"elements":[
"Paragraph1",,
"Paragraph2",
"Codesnippet1",,
"Paragraph3",,
"Codesnippet2",
]
}
How would I be able to achieve the desired behaviour?
Thanks for the help!
EDIT - XSLT 1.0 solution:
I've solved the issue with the solution from #Christian Mosz, using apply-templates and checking following-sibling:
<!-- Method template -->
<xsl:template name="method">
{
"title":"<xsl:value-of select="normalize-space(desc_signature/desc_name)" />",
"elements":[
<xsl:apply-templates select="desc_content/*"/>
]
}
</xsl:template>
<!-- Paragraph template -->
<xsl:template match="paragraph">
{"paragraph":"<xsl:value-of select="normalize-space()"/>"}
<xsl:if test="following-sibling::paragraph|following-sibling::literal_block">,</xsl:if>
</xsl:template>
<!-- Code snippet template -->
<xsl:template match="literal_block">
{"code":"<xsl:call-template name="code"/>"}
<xsl:if test="following-sibling::paragraph|following-sibling::literal_block">,</xsl:if>
</xsl:template>
For XSLT 3.0, please check approved answer.
Using XSLT 3 (e.g. with Saxon 9.8 or later or AltovaXML 2017 R3 or later) you have two options, you can either construct an XPath 3.1 map:
map {
'title' : normalize-space(desc_signature/desc_name),
'elements' : array {
data(desc_content/(paragraph | literal_block))
}
}
i.e.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="json" indent="yes" />
<xsl:template match="method">
<xsl:sequence
select="map {
'title' : normalize-space(desc_signature/desc_name),
'elements' : array {
data(desc_content/(paragraph | literal_block))
}
}"/>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/pNmC4HJ
or you transform to the XML representation of JSON the xml-to-json functions supports:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/2005/xpath-functions"
expand-text="yes"
exclude-result-prefixes="#all"
version="3.0">
<xsl:output method="text" indent="yes" />
<xsl:template match="/">
<xsl:variable name="json-xml">
<xsl:apply-templates/>
</xsl:variable>
<xsl:value-of select="xml-to-json($json-xml, map { 'indent' : true() })"/>
</xsl:template>
<xsl:template match="method">
<map>
<string key="title">{normalize-space(desc_signature/desc_name)}</string>
<array key="elements">
<xsl:apply-templates select="desc_content/(paragraph | literal_block)"/>
</array>
</map>
</xsl:template>
<xsl:template match="desc_content/*">
<string>{.}</string>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/pNmC4HJ/1

Converting an RSS pubDate to a mySQL time stamp format using XSLT

I've got a little tool which strips out and re-arranges an iTunes formatted RSS feed and converts it to a nice simple XML file.
I then import the cleansed XML into mySQL to do things with later.
I need to be able to convert the pubDate in the feed to a mySQL timestamp so I can import this properly into a TIMESTAMP field in my table.
I'm having some issues with it.
My current XSL file does a tidy up on the date, but I don't need this at all.
I just want the <pubDate> node to have the correct mySQL friendly timestamp inside instead.
I've not yet managed to find anything which does what I need. Any pointers?
Here is my XSLT file...
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:cc="http://web.resource.org/cc/"
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
xmlns:libsyn="http://libsyn.com/rss-extension"
xmlns:media="http://search.yahoo.com/mrss/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
exclude-result-prefixes="atom cc itunes libsyn media rdf">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<data>
<entries>
<xsl:apply-templates select="rss/channel/item"></xsl:apply-templates>
</entries>
</data>
</xsl:template>
<xsl:template match="item">
<entry>
<title><xsl:value-of select="title"/></title>
<link><xsl:value-of select="link"/></link>
<description><xsl:value-of select="description" disable-output-escaping="yes"/></description>
<subtitle><xsl:value-of select="itunes:subtitle"/></subtitle>
<pubDate><xsl:value-of select="pubDate"/></pubDate>
<xsl:apply-templates select="pubDate"/>
<explicit><xsl:value-of select="itunes:explicit"/></explicit>
<podcastImage><xsl:value-of select="itunes:image/#href"/></podcastImage>
<podcastURL><xsl:value-of select="enclosure/#url"/></podcastURL>
<podcastLength><xsl:value-of select="enclosure/#length"/></podcastLength>
<podcastDuration><xsl:value-of select="itunes:duration"/></podcastDuration>
</entry>
</xsl:template>
<xsl:template match="pubDate">
<date>
<xsl:attribute name="time"><xsl:value-of select="substring(text(),18,5)"/></xsl:attribute>
<xsl:call-template name="format-from-rfc-to-iso">
<xsl:with-param name="rfc-date" select="text()"/>
</xsl:call-template>
</date>
</xsl:template>
<xsl:template name="format-from-rfc-to-iso">
<xsl:param name="rfc-date"/>
<xsl:param name="day-with-zero" select="format-number(substring(substring($rfc-date,6,11),1,2),'00')"/>
<xsl:param name="month-with-zero">
<xsl:if test="contains($rfc-date,'Jan')">01</xsl:if>
<xsl:if test="contains($rfc-date,'Feb')">02</xsl:if>
<xsl:if test="contains($rfc-date,'Mar')">03</xsl:if>
<xsl:if test="contains($rfc-date,'Apr')">04</xsl:if>
<xsl:if test="contains($rfc-date,'May')">05</xsl:if>
<xsl:if test="contains($rfc-date,'Jun')">06</xsl:if>
<xsl:if test="contains($rfc-date,'Jul')">07</xsl:if>
<xsl:if test="contains($rfc-date,'Aug')">08</xsl:if>
<xsl:if test="contains($rfc-date,'Sep')">09</xsl:if>
<xsl:if test="contains($rfc-date,'Oct')">10</xsl:if>
<xsl:if test="contains($rfc-date,'Nov')">11</xsl:if>
<xsl:if test="contains($rfc-date,'Dec')">12</xsl:if>
</xsl:param>
<xsl:param name="year-full" select="format-number(substring(substring($rfc-date,6,11),7,5),'####')"/>
<xsl:param name="rfc-date-to-iso" select="concat($year-full,'-',$month-with-zero,'-',$day-with-zero)"/>
<xsl:value-of select="$rfc-date-to-iso"/>
</xsl:template>
</xsl:stylesheet>
The current date/time looks like this from the rss feed:
<pubDate>Sun, 07 Feb 2016 00:00:56 -0500</pubDate>
I'd like it to by displayed like this so it can be inserted into mySQL:
<pubDate>2016-02-07 00:00:56</pubDate>
I use PHP to process this.
$xml = new DOMDocument;
$xml->load('podbean.xml');
$xsl = new DOMDocument;
$xsl->load('podbean.xsl');
// Configure the transformer
$proc = new XSLTProcessor;
$proc->importStyleSheet($xsl); // attach the xsl rules
$proc->transformToXML($xml);
$proc->transformToURI($xml,'itunes.xml');
Simon
Using a processor that supports the EXSLT str:tokenize() function (as libxslt does), you can do something like this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="str">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- ... -->
<xsl:template match="item">
<entry>
<!-- ... -->
<pubDate>
<xsl:variable name="date-tokens" select="str:tokenize(pubDate, ' ' )" />
<!-- year -->
<xsl:value-of select="$date-tokens[4]" />
<xsl:text>-</xsl:text>
<!-- month -->
<xsl:variable name="mmm" select="$date-tokens[3]" />
<xsl:variable name="m" select="string-length(substring-before('JanFebMarAprMayJunJulAugSepOctNovDec', $mmm)) div 3 + 1" />
<xsl:value-of select="format-number($m, '00')" />
<xsl:text>-</xsl:text>
<!-- day -->
<xsl:value-of select="format-number($date-tokens[2], '00')" />
<xsl:text> </xsl:text>
<!-- time -->
<xsl:value-of select="$date-tokens[5]" />
</pubDate>
<!-- ... -->
</entry>
</xsl:template>
</xsl:stylesheet>

XSL Delimited Values for HTML Links and their Descriptions

I am trying to debug some xsl code that puts links gathered from an XML Document with their descriptions in a list, it seems to be working, except when handling multiple links gathered from a single string that are delimited with a "|" and "^" symbol.
The XML Line that contains this code is very similar to this:
<WebContent>
<content_type_desc>Links</content_type_desc>
<content_value>Google|http://www.google.com^Yahoo|http://www.yahoo.com^Bing|Http://www.bing.com</content_value>
</WebContent>
The xsl that handles this is like
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="html" indent="yes" encoding="utf-8"/>
<xsl:template match="/">
<!--Links-->
<xsl:variable name="links" select="//WebContent[content_type_desc='Links']/content_value "/>
<!--Links-->
<!--Links section-->
<xsl:if test="$links != ''">
<br />
<xsl:choose>
<xsl:when test="contains($links,'^')">
<xsl:variable name="URL" select="substring-after(substring-before($links,'^'),'|')"/>
<xsl:variable name="URLText" select="substring-before($links,'|')"/>
<strong>Links: </strong><br />
<xsl:value-of select="$URLText"/>
<br />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="URL" select="substring-after($links,'|')"/>
<xsl:variable name="URLText" select="substring-before($links,'|')"/>
<strong>Links: </strong><br />
<xsl:value-of select="$URLText"/>
<br />
</xsl:otherwise>
</xsl:choose>
<br />
</xsl:if>
<!--Links section-->
</xsl:template>
</xsl:stylesheet>
What's wrong with this is that it only outputs
<a href="http://www.google.com>Google</a>
When I would like it to output
<a href="http://www.google.com>Google</a>
<a href="http://www.yahoo.com>Yahoo</a>
<a href="http://www.bing.com>Bing</a>
Any help will be greatly appreciated as this has me completely stumped.
Assuming you are actually only using XSLT 1.0, to solve this you could make use of a named-template which is called recursively.
At the moment, the code is only processing the URL before the first ^ in the code. What you could do is put the main bulk of the code that checks the links variable in a named template. Then, in the xsl:when condition that runs when the URL does contain a ^ you add a recursive call to the named template, but passing in only the substring after the ^.
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="html" indent="yes" encoding="utf-8"/>
<xsl:template match="/">
<xsl:param name="links" select="//WebContent[content_type_desc='Links']/content_value "/>
<xsl:if test="$links != ''">
<strong>Links: </strong>
<br />
<xsl:call-template name="splitlinks">
<xsl:with-param name="links" select="$links" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="splitlinks">
<xsl:param name="links" />
<xsl:choose>
<xsl:when test="contains($links,'^')">
<xsl:variable name="URL" select="substring-after(substring-before($links,'^'),'|')"/>
<xsl:variable name="URLText" select="substring-before($links,'|')"/>
<xsl:value-of select="$URLText"/>
<br />
<xsl:call-template name="splitlinks">
<xsl:with-param name="links" select="substring-after($links,'^')" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="URL" select="substring-after($links,'|')"/>
<xsl:variable name="URLText" select="substring-before($links,'|')"/>
<xsl:value-of select="$URLText"/>
<br />
</xsl:otherwise>
</xsl:choose>
<br />
</xsl:template>
</xsl:stylesheet>
Given that you have tagged your question as classic ASP your XSLT processor is likely some version of MSXML for which there is an implementation of http://www.exslt.org/str/functions/tokenize/index.html so you could use that.

Transform a xml to a string using xslt?

How can I transform the xml in format1 to a string as mentioned in format2 using XSLT?
format 1
<children>
<child data="test1">
<content><name>test1</name>
<child>
<content><name>test1child</name>
</child>
</child>
</children>
format 2
"<root>"
+"<item id='test1'>"
+"<content><name>test1</name></content>"
+"<item parent_id='test1'>"
+"<content><name>test1child</name>"
+"</content>"
+"</item>"
+</item>
+"<root>"
so children should replace with root, child should replaced with item and child of child should be replaced with *item parent_id of parent id*. Is it possible to do with xslt?
Assuming XSLT 2.0, here is some suggestion on how to approach that, assuming you really want some string output with quotes and plus symbols (to get Javascript or similar code to construct XML as a string?):
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="text"/>
<xsl:template match="*">
<xsl:param name="name" select="name()"/>
<xsl:text><</xsl:text>
<xsl:value-of select="$name"/>
<xsl:apply-templates select="#*"/>
<xsl:text>></xsl:text>
<xsl:apply-templates/>
<xsl:text></</xsl:text>
<xsl:value-of select="$name"/>
<xsl:text>></xsl:text>
</xsl:template>
<xsl:template match="#*">
<xsl:param name="name" select="name()"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$name"/>
<xsl:text>='</xsl:text>
<xsl:value-of select="."/>
<xsl:text>'</xsl:text>
</xsl:template>
<xsl:template match="text()[matches(., '^\s+$')]">
<xsl:text>"
+"</xsl:text>
</xsl:template>
<xsl:template match="/children">
<xsl:text>"</xsl:text>
<xsl:next-match>
<xsl:with-param name="name" select="'root'"/>
</xsl:next-match>
<xsl:text>"</xsl:text>
</xsl:template>
<xsl:template match="child">
<xsl:next-match>
<xsl:with-param name="name" select="'item'"/>
</xsl:next-match>
</xsl:template>
<xsl:template match="child//child">
<xsl:variable name="copy" as="element()">
<xsl:copy>
<xsl:attribute name="parent_id" select="ancestor::child[1]/#data"/>
<xsl:copy-of select="#* , node()"/>
</xsl:copy>
</xsl:variable>
<xsl:apply-templates select="$copy"/>
</xsl:template>
</xsl:stylesheet>
That transforms the input
<children>
<child data="test1">
<content><name>test1</name></content>
<child>
<content><name>test1child</name></content>
</child>
</child>
</children>
into the result
"<root>"
+"<item data='test1'>"
+"<content><name>test1</name></content>"
+"<item parent_id='test1'>"
+"<content><name>test1child</name></content>"
+"</item>"
+"</item>"
+"</root>"
The code so far has many shortcomings however as it would not construct well-formed XML with properly escaped attribute values and also does not care to output namespace declarations. You could however adapt more sophisticated solutions like http://lenzconsulting.com/xml-to-string/.

How to call template with name as a variable in XSLT?

I have the following XML document which needs to be parsed with an XSLT to HTML.
<root>
<c>
<c1>
<id>1</id>
<text>US</text>
</c1>
<c1>
<id>2</id>
<text>UK</text>
</c1>
</c>
</root>
The XSLT for converting this to HTML is given below.
<?xml version="1.0" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" />
<xsl:template match="root">
<html>
<xsl:for-each select="c/c1">
**<xsl:variable name="vTemplate" select="text"/>
<xsl:apply-templates select="$vTemplate[#name='text'"/>**
</xsl:for-each>
</html>
</xsl:template>
<xsl:template match="xsl:template[#name='text']" name="text">
<select>
<xsl:attribute name="id">
<xsl:value-of select="id"/>
</xsl:attribute>
</select>
</xsl:template>
</xsl:stylesheet>
I need to call a template depends up on the text field. So for the value US, one template will be executed and for UK, another will executed.
How to achieve this with a variable as a template name while calling the template? I just made a try but it gives error. Can someone help me to figure out where i made wrong?
I think it is not possible to choose name of template to be called dynamically. What could be done is xsl:choose utilization (perhaps with combination with mode attribute), like this
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<html>
<xsl:for-each select="c/c1">
<xsl:choose>
<xsl:when test="text = 'US'">
<xsl:apply-templates select="text" mode="US"/>
</xsl:when>
<xsl:when test="text = 'UK'">
<xsl:apply-templates select="text" mode="UK"/>
</xsl:when>
<xsl:otherwise>
<xsl:comment>Something's wrong</xsl:comment>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</html>
</xsl:template>
<xsl:template match="text" mode="US">
<xsl:comment>US mode</xsl:comment>
<select>
<xsl:attribute name="id">
<xsl:value-of select="preceding-sibling::id"/>
</xsl:attribute>
</select>
</xsl:template>
<xsl:template match="text" mode="UK">
<xsl:comment>UK mode</xsl:comment>
<select>
<xsl:attribute name="id">
<xsl:value-of select="preceding-sibling::id"/>
</xsl:attribute>
</select>
</xsl:template>
</xsl:stylesheet>
Or you can use match with appropriate predicate and avoid for-each like this
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<html>
<xsl:apply-templates select="//c1" />
</html>
</xsl:template>
<xsl:template match="c1[text = 'US']">
<xsl:comment>US mode</xsl:comment>
<select id="{id}" />
</xsl:template>
<xsl:template match="c1[text = 'UK']">
<xsl:comment>UK mode</xsl:comment>
<select id="{id}" />
</xsl:template>
</xsl:stylesheet>
The id attribute of select can be also filled by "Attribute value templates" (xpath in curly brackets) as shown in previous sample.