Преобразование списка с разделителями переменной длины в XML с использованием XSLT 1.0 - PullRequest
0 голосов
/ 08 сентября 2018

Ввод текста должен быть преобразован в вывод XML с использованием XSLT 1.0. Список имеет переменную длину с разделителем |.

Введите:

name=IMON_EVENT;next_state=SET_IMON;is_enabled=true; | name=MAIN_BATCH;next_state=BATCH01;is_enabled=false;priority=9;

Ожидаемый результат:

<time-triggers>
    <trigger>
        <name>IMON_EVENT</name>
        <next_state>SET_IMON</next_state>
        <is_enabled>true</is_enabled>
    </trigger>
    <trigger>
        <name>MAIN_BATCH</name>
        <next_state>BATCH01</next_state>
        <is_enabled>false</is_enabled>
        <priority>9</priority>
    </trigger>
</time-triggers>

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Размещение исходной строки в скрипте XSLT - плохая практика, особенно если вы хотите обрабатывать различные входные данные.

Если вы можете использовать XSLT версии 2.0, вам лучше использовать следующие функции:

  • unparsed-text-available - чтобы проверить, существует ли входной файл,
  • unparsed-text - чтобы прочитать содержимое этого файла в переменную.

Остальная часть сценария (как обработать прочитанное содержимое) может быть такой же, как в другом ответе.

0 голосов
/ 08 сентября 2018

Для XSLT 1.0 вы можете использовать рекурсивные вызовы шаблонов, которые проверяют наличие разделителей, и использовать substring-before() и substring-after()

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

    <xsl:output indent="yes"/>

    <xsl:template match="/">
        <xsl:variable name="triggers" select="'name=IMON_EVENT;next_state=SET_IMON;is_enabled=true; | name=MAIN_BATCH;next_state=BATCH01;is_enabled=false;priority=9;'"/>

        <triggers>
            <xsl:call-template name="make-trigger">
                <xsl:with-param name="val" select="$triggers"/>
            </xsl:call-template> 
        </triggers>   
    </xsl:template>

    <xsl:template name="make-trigger">
        <xsl:param name="val"/>

        <xsl:if test="normalize-space($val)">
            <xsl:choose>
                <xsl:when test="contains($val, '|')">
                    <trigger>
                    <xsl:call-template name="make-elements">
                        <xsl:with-param name="val" select="substring-before($val, '|')"/>
                    </xsl:call-template>
                    </trigger>
                    <xsl:call-template name="make-trigger">
                        <xsl:with-param name="val" select="substring-after($val, '|')"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <trigger>
                    <xsl:call-template name="make-elements">
                        <xsl:with-param name="val" select="$val"/>
                    </xsl:call-template>
                    </trigger>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:if>
    </xsl:template>

    <xsl:template name="make-elements">
        <xsl:param name="val"/>

        <xsl:if test="contains($val, '=')">
            <xsl:choose>
                <xsl:when test="contains($val, ';')">
                    <xsl:call-template name="make-element">
                        <xsl:with-param name="val" select="substring-before($val, ';')"/>
                    </xsl:call-template>
                    <xsl:call-template name="make-elements">
                        <xsl:with-param name="val" select="substring-after($val, ';')"/>
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:call-template name="make-element">
                        <xsl:with-param name="val" select="$val"/>
                    </xsl:call-template>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:if>
    </xsl:template>

    <xsl:template name="make-element">
        <xsl:param name="val"/>

        <xsl:element name="{normalize-space(substring-before($val, '='))}">
            <xsl:value-of select="substring-after($val, '=')"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

Ниже приведено решение XSLT 2.0 , в котором используется функция tokenize() для разделения значений на разделители | и ; с вложенными xsl:for-each для обработки последовательности значений, xsl:analyze-string для захвата имени и значения между = и xsl:element для создания динамически именованных элементов из групп захвата регулярных выражений .

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

  <xsl:output indent="yes"/>

  <xsl:template match="/">
    <xsl:variable name="triggers" select="'name=IMON_EVENT;next_state=SET_IMON;is_enabled=true; | name=MAIN_BATCH;next_state=BATCH01;is_enabled=false;priority=9;'"/>

    <triggers>
      <xsl:for-each  select="tokenize($triggers, '\s*\|\s*')">
        <trigger>
          <xsl:for-each select="tokenize(., '\s*;\s*')">
              <xsl:analyze-string select="." regex="(.+)=(.*)">
                  <xsl:matching-substring>
                      <xsl:element name="{regex-group(1)}">
                          <xsl:value-of select="regex-group(2)"/>
                      </xsl:element>
                  </xsl:matching-substring>
              </xsl:analyze-string> 
          </xsl:for-each>
        </trigger>  
      </xsl:for-each>
    </triggers>

  </xsl:template>

</xsl:stylesheet>
...