树状结构平面文件到动态XSLT

时间:2019-05-12 05:00:47

标签: java json xslt inputstream flat-file

我有一个树形的平面文件,需要将其写入动态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 :(得分:0)

这里是一个使用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

如果确实是通过使用xsl:namespace-alias来达到目的,则该解决方案当然可以调整为输出XSLT。