Древовидная структура плоского файла в динамический XSLT - PullRequest
0 голосов
/ 12 мая 2019

У меня есть плоский древовидный файл, для которого мне нужно записать в динамический XSLT.Данные плоского файла постоянно меняются.Например, у меня есть тег A, B, C, D, как указано ниже.Тогда следующий файл может иметь E, F, G, H. Само дерево будет иметь 4-6 уровней глубины.

Я могу прочитать файл в простом списке с циклом каждой строки, но не могу создать егодревовидная структура в XSLT.Я хочу прочитать то же самое в Java-объекте, а затем создать то же самое в XSLT.

Для чтения файла:

while ((item = in.readLine()) != null) {
lineNo++;
String rowContent = item;
}

Входной файл:


    Element A
       Element B
          Element C
             Data
          Element D
             Data

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

<xsl:template match="/">
<A>
<B>
<C><xsl:text>data</xsl:text></C>
<D><xsl:text>data</xsl:text></D>
</B>
</A>
</xsl:template>

Я новичок в XSLT, любая помощь будет оценена.Спасибо !!!

1 Ответ

0 голосов
/ 16 мая 2019

Вот пример использования XSLT 3 для анализа и группировки и вложения ваших текстовых данных в иерархический XML:

<?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:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="input-string" as="xs:string">    Element A
       Element B
          Element C
             Data
          Element D
             Data</xsl:param>

  <xsl:output method="xml" indent="yes"/>

  <xsl:function name="mf:nest" as="node()*">
      <xsl:param name="input" as="map(xs:string, item())*"/>
      <xsl:variable name="min-level" as="xs:integer" select="min($input?level)"/>
      <xsl:for-each-group select="$input" group-starting-with=".[?level = $min-level and ?type = 'element']">
          <xsl:choose>
              <xsl:when test="?type = 'element'">
                  <xsl:element name="{?name}">
                      <xsl:sequence select="mf:nest(tail(current-group()))"/>
                  </xsl:element>
              </xsl:when>
              <xsl:otherwise>
                  <xsl:value-of select="?value"/>
              </xsl:otherwise>
          </xsl:choose>
      </xsl:for-each-group>
  </xsl:function>

  <xsl:template name="xsl:initial-template" match="/">
    <xsl:variable name="lines" as="map(xs:string, item())*"
      select="tokenize($input-string, '\n') ! 
              analyze-string(., '^( *)(((Element) (\w+))|(.+))') ! *:match ! 
              map { 
                'type' : if (.//*:group[@nr = 4] = 'Element') then 'element' else 'data',
                'name' : string(.//*:group[@nr = 5]),
                'level' : string-length(*:group[@nr = 1]),
                'value' : string(.//*:group[@nr = 6]) 
              }"/>
    <xsl:sequence select="mf:nest($lines)"/>
  </xsl:template>

</xsl:stylesheet>

Выходные данные - простой XML

<A>
   <B>
      <C>Data</C>
      <D>Data</D>
   </B>
</A>

https://xsltfiddle.liberty -development.net / 6r5Gh3y / 2

Конечно, решение можно адаптировать для вывода XSLT, если это действительно цель, с использованием xsl:namespace-alias.

...