【问题标题】:Tree structure flat file to dynamic XSLT树结构平面文件到动态 XSLT
【发布时间】:2019-09-29 11:16:48
【问题描述】:

我有一个树形结构的平面文件,我需要将其写入动态 XSLT。平面文件数据不断变化。例如,我有标签 A、B、C、D,如下所示。然后下一个文件可以有 E、F、G、H。树本身会有 4-6 级的深度。

我可以将文件读入循环每一行的普通列表,但无法在 XSLT 中创建相同的树结构。我想在 java 对象中读取相同的内容,然后在 XSLT 中创建相同的内容。

读取文件:

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

输入文件:

元素 A 元素 B 元素 C 数据 元素 D 数据

预期输出 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 的新手,如有任何帮助,我们将不胜感激。谢谢!!!

【问题讨论】:

  • 您如何通过缩进量来区分该输入格式中的级别?格式是否字面意思是“元素 A”?而且我不明白为什么要将非 XML 格式转换为 XSLT,毕竟 XSLT 程序应该解析和处理 XML 输入文件。您需要 XSLT 做什么?

标签: java json xslt inputstream flat-file


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 2021-11-05
    • 2013-01-22
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多