0

下面是要使用 XSLT 转换为 XML 的三行数据(制表符分隔)。

Column_1     Column_2     Column_3     Column_4
A            B            C            D
A            B            A            F
C            B            D            C

预期输出如下

<firstTag Column_1 ='A' Column_2='B'>
   <secondTag Column_3='C'  Column_4='D'/>
   <secondTag Column_3='A'  Column_4='F'/>
</firstTag>
<firstTag Column_1 ='C' Column_2='B'>
   <secondTag Column_3='D'  Column_4='C'/>
</firstTag>

如何使用 XSLT 基于一个或多个属性值(Column_1 和 Column_2)对这些行进行分组

4

1 回答 1

0

您可以使用unparsed-textor (在自 2017 年以来由 Saxon 9.8 及更高版本支持的 XSLT 3 中)unparsed-text-lines处理非 XML 文本文件,就像您似乎拥有的那样,然后您拥有tokenize函数加上xsl:analyze-string元素或在 XSLT 3analyze-string中处理和构造函数您的制表符将数据分隔成您可以提供给的东西xsl:for-each-group,即 XSLT 3 中的一些 XML 或一些数组和字符串序列的混合。

XSLT 2 和 3 中的分组包含在https://stackoverflow.com/tags/xslt-grouping/info中。

下面是一个使用 XSLT 3 的示例,并for-each-group在一个由字符串数组组成的分组人口中:

<?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:math="http://www.w3.org/2005/xpath-functions/math"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    xmlns:array="http://www.w3.org/2005/xpath-functions/array"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="text" as="xs:string">Column_1     Column_2     Column_3     Column_4
A            B            C            D
A            B            A            F
C            B            D            C</xsl:param>


  <xsl:param name="el1" as="xs:string">firstElement</xsl:param>
  <xsl:param name="el2" as="xs:string">secondElement</xsl:param>

  <xsl:variable name="rows" as="array(xs:string)*" select="($text => tokenize('\r?\n')) ! array { tokenize(., '\s+') }"/>
  
  <xsl:variable name="data-rows" select="$rows => tail()"/>
  
  <xsl:variable name="column-names" select="$rows[1]?*"/>

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

  <xsl:template match="/" name="xsl:initial-template">
    <result>
        <xsl:for-each-group select="$data-rows" composite="yes" group-by="?1, ?2">
            <xsl:element name="{$el1}">
                <xsl:attribute name="{$column-names[1]}" select="current-grouping-key()[1]"/>
                <xsl:attribute name="{$column-names[2]}" select="current-grouping-key()[2]"/>
                <xsl:apply-templates select="current-group()"/>
            </xsl:element>
        </xsl:for-each-group>
    </result>
  </xsl:template>
  
  <xsl:template match=".[. instance of array(xs:string)]">
      <xsl:element name="{$el2}">
          <xsl:for-each select="?(3 to array:size(current()))">
              <xsl:attribute name="{subsequence($column-names, position() + 2, 1)}" select="."/>
          </xsl:for-each>
      </xsl:element>
  </xsl:template>
  
</xsl:stylesheet>

当我从您的问题中复制输入样本时,它似乎不包含制表符,所以我改为使用空格进行标记。

于 2020-06-30T16:08:29.637 回答