0

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?

5
  • Which XSLT processor do you want to use, which XSLT version? If XML is used as the data format and XSLT is used as the processing language then what kind of XML structure or XSLT known data type is SET:[a, b, c, d, e] supposed to represent? Commented Apr 22, 2020 at 14:58
  • As I said I can modify it to e.g. [a, b, c, d, e]. I just want to know if there is any way to provide multiple options in one attribute. I'm also not strictly bound to versions of anything. I'm flexible with this. Commented Apr 22, 2020 at 15:21
  • Do you find that representation in w3.org/TR/xml/#sec-attribute-types? Or in w3.org/TR/xmlschema-2/#built-in-derived? And which XSLT processor, which XSLT version can you use? Commented Apr 22, 2020 at 15:29
  • Hmm. I think there is no representation like I wrote. As I said, I can use any version of XSLT, just to make it work. For now, my XSL file uses <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">. So there isn't completely any way to get some strings divided by comma or whatever in XML attribute? Commented Apr 22, 2020 at 16:11
  • There a list data types like NMTOKENS but you partly depend on DTD or schema support. And of course XSLT 2 with XPath 2 functions has functions like tokenize. With an XSLT 1 processor there might be support for an extension function doing the job. But it will short fall if your data gets more complex and the token separator can appear in your data values. Commented Apr 22, 2020 at 16:31

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

Comments

1

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.