根据 XML 个属性对 XML 个值进行分组 (XSLT)
Grouping XML Values Based On XML Attributes (XSLT)
下面是要使用 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)对这些行进行分组
您可以使用 unparsed-text
或(在 Saxon 9.8 及更高版本自 2017 年以来支持的 XSLT 3 中)unparsed-text-lines
来处理非 XML 文本文件,就像您似乎拥有的那样,然后你有 tokenize
函数加上 xsl:analyze-string
元素或在 XSLT 3 中 analyze-string
函数来处理和构建你的制表符分隔数据,使其成为你可以提供给 xsl:for-each-group
的东西,即 XSLT 3.XML 中的一些 XML 或一些数组和字符串序列的混合。
XSLT 2 和 3 中的分组在 https://whosebug.com/tags/xslt-grouping/info 中介绍。
Here is an example using 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>
当我从你的问题中复制输入样本时,它似乎不包含制表符,所以我改为用空格标记。
下面是要使用 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)对这些行进行分组您可以使用 unparsed-text
或(在 Saxon 9.8 及更高版本自 2017 年以来支持的 XSLT 3 中)unparsed-text-lines
来处理非 XML 文本文件,就像您似乎拥有的那样,然后你有 tokenize
函数加上 xsl:analyze-string
元素或在 XSLT 3 中 analyze-string
函数来处理和构建你的制表符分隔数据,使其成为你可以提供给 xsl:for-each-group
的东西,即 XSLT 3.XML 中的一些 XML 或一些数组和字符串序列的混合。
XSLT 2 和 3 中的分组在 https://whosebug.com/tags/xslt-grouping/info 中介绍。
Here is an example using 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>
当我从你的问题中复制输入样本时,它似乎不包含制表符,所以我改为用空格标记。