Reputation: 31
I'm using XSLT to create HTML forms from XML. Forms are dynamically created. There is no ready teamplate for that. There will be as many inputs as user wants. I want to keep it as short as possible so I'm using attributes to create e.g. options in select tags. The problem is that I can't figure out how to turn this XML:
<input mapTo="dropdown" nameId="sampleId" inputDomain="[a, b, c, d, e]" />
into:
<select id="sampleId">
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
<option value="d">d</option>
<option value="e">e</option>
</select>
My problem is exactly the inputDomain
attribute. I can modify for an easier method but I want to keep it in one attribute (like an array). Is it possible? Or maybe you have more convenient ideas?
Upvotes: 0
Views: 283
Reputation: 167696
If you use schema-aware XSLT 2 or 3 (e.g. with Saxon 9 or 10 EE) you can declare the attribute as type xs:NMTOKENS
and use a space separated list:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="input">
<xs:complexType>
<xs:attribute name="inputDomain" type="xs:NMTOKENS" use="required"/>
<xs:attribute name="mapTo" use="required" type="xs:NCName"/>
<xs:attribute name="nameId" use="required" type="xs:NCName"/>
</xs:complexType>
</xs:element>
</xs:schema>
Then a stylesheet processing
<input mapTo="dropdown" nameId="sampleId" inputDomain="a b c d e" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd"/>
can use the data
function on the attribute to have a sequence of tokens:
<?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"
expand-text="yes"
exclude-result-prefixes="#all"
version="3.0">
<xsl:template match="input[@mapTo = 'dropdown']">
<select id="{@nameId}">
<xsl:for-each select="data(@inputDomain)">
<option value="{.}">{.}</option>
</xsl:for-each>
</select>
</xsl:template>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:template match="/">
<html>
<head>
<title>Example</title>
</head>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1
Reputation: 117073
Consider the following example:
XML
<input mapTo="dropdown" nameId="sampleId" inputDomain="a,b,c,d,e" />
XSLT 2.0
<xsl:stylesheet version="2.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="input">
<select id="sampleId">
<xsl:for-each select="tokenize(@inputDomain, ',')">
<option value="{.}">
<xsl:value-of select="." />
</option>
</xsl:for-each>
</select>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<select id="sampleId">
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
<option value="d">d</option>
<option value="e">e</option>
</select>
Demo: http://xsltfiddle.liberty-development.net/3MvmXiL
Upvotes: 1