Разобрать атрибут XSLT как массив - PullRequest
0 голосов
/ 22 апреля 2020

Я использую XSLT для создания HTML форм из XML. Формы создаются динамически. Для этого нет готовой команды. Там будет столько входов, сколько хочет пользователь. Я хочу, чтобы он был как можно короче, поэтому я использую атрибуты, например, для создания опций в тегах выбора. Проблема в том, что я не могу понять, как превратить этот XML:

<input mapTo="dropdown" nameId="sampleId" inputDomain="[a, b, c, d, e]" />

в:

<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>

Моя проблема - это именно атрибут inputDomain. Я могу изменить для более простого метода, но я хочу сохранить его в одном атрибуте (например, массив). Является ли это возможным? А может у вас есть более удобные идеи?

Ответы [ 2 ]

0 голосов
/ 23 апреля 2020

Если вы используете XSLT 2 или 3 с поддержкой схемы (например, с Saxon 9 или 10 EE), вы можете объявить атрибут как тип xs:NMTOKENS и использовать список через пробел:

<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>

Тогда При обработке таблицы стилей

<input mapTo="dropdown" nameId="sampleId" inputDomain="a b c d e" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd"/>

можно использовать функцию data для атрибута для получения последовательности токенов:

<?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>
0 голосов
/ 22 апреля 2020

Рассмотрим следующий пример:

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>

Результат

<?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>

Демо : http://xsltfiddle.liberty-development.net/3MvmXiL

...