遵循以下所述的方法:Converting CSV to hierarchichal XML using XSLT
现在,原始输入文件将包含空标记,如下所示:
<root>
GroupName,GroupValue,SubGroupName,SubGroupValue,ItemName,ItemValue
,A,1,C,1,G
1,,1,C,2,H
1,A,2,D,1,I
</root>
提供的原始XSLT 1.0是:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="k1" match="row" use="cell[1]"/>
<xsl:key name="k2" match="row" use="concat(cell[1], '|', cell[3])"/>
<xsl:template match="/">
<!-- tokenize csv -->
<xsl:variable name="rows">
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="root"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="data">
<xsl:for-each select="exsl:node-set($rows)/row[position() > 1]">
<row>
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="delimiter" select="','"/>
<xsl:with-param name="name" select="'cell'"/>
</xsl:call-template>
</row>
</xsl:for-each>
</xsl:variable>
<!-- output -->
<document>
<xsl:for-each select="exsl:node-set($data)/row[count(. | key('k1', cell[1])[1]) = 1]">
<group>
<name>
<xsl:value-of select="cell[1]"/>
</name>
<value>
<xsl:value-of select="cell[2]"/>
</value>
<xsl:for-each select="key('k1', cell[1])[count(. | key('k2', concat(cell[1], '|', cell[3]))[1]) = 1]">
<subgroup>
<name>
<xsl:value-of select="cell[3]"/>
</name>
<value>
<xsl:value-of select="cell[4]"/>
</value>
<items>
<xsl:for-each select="key('k2', concat(cell[1], '|', cell[3]))">
<item>
<name>
<xsl:value-of select="cell[5]"/>
</name>
<value>
<xsl:value-of select="cell[6]"/>
</value>
</item>
</xsl:for-each>
</items>
</subgroup>
</xsl:for-each>
</group>
</xsl:for-each>
</document>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="text"/>
<xsl:param name="delimiter" select="' '"/>
<xsl:param name="name" select="'row'"/>
<xsl:variable name="token" select="substring-before(concat($text, $delimiter), $delimiter)" />
<xsl:if test="$token">
<xsl:element name="{$name}">
<xsl:value-of select="$token"/>
</xsl:element>
</xsl:if>
<xsl:if test="contains($text, $delimiter)">
<!-- recursive call -->
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="substring-after($text, $delimiter)"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
<xsl:with-param name="name" select="$name"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
如何调整xslt以便在这种情况下不会跳过空标记并生成以下xml输出?
<?xml version="1.0" encoding="utf-8"?>
<Document>
<data>
<GroupName></GroupName>
<GroupValue>A</GroupValue>
...
</data>
<data>
<GroupName>1</GroupName>
<GroupValue></GroupValue>
...
</data>
<data>
<GroupName>1</GroupName>
<GroupValue>A</GroupValue>
...
</data>
</Document>
答案 0 :(得分:0)
试试这个:
您也可以在http://xsltransform.net/nb9MWt1/2
查看此信息<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:output indent="yes"/>
<xsl:variable name="elements">
<element>GroupName</element>
<element>GroupValue</element>
<element>SubGroupName</element>
<element>SubGroupValue</element>
<element>ItemName</element>
<element>ItemValue</element>
</xsl:variable>
<xsl:template match="root">
<Document>
<xsl:call-template name="row">
<xsl:with-param name="data" select="."/>
</xsl:call-template>
</Document>
</xsl:template>
<xsl:template name="row">
<xsl:param name="data"/>
<xsl:choose>
<xsl:when test="contains($data, '
')">
<xsl:if test="normalize-space(substring-before($data, '
')) != ''">
<data>
<xsl:call-template name="cell">
<xsl:with-param name="celldata" select="substring-before($data, '
')"/>
<xsl:with-param name="position" select="1"/>
</xsl:call-template>
</data>
</xsl:if>
<xsl:if test="normalize-space(substring-after($data, '
')) != ''">
<xsl:call-template name="row">
<xsl:with-param name="data" select="substring-after($data, '
')"/>
<xsl:with-param name="position" select="1"/>
</xsl:call-template>
</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="normalize-space($data) != ''">
<data>
<xsl:call-template name="cell">
<xsl:with-param name="celldata" select="$data"/>
<xsl:with-param name="position" select="1"/>
</xsl:call-template>
</data>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="cell">
<xsl:param name="celldata"/>
<xsl:param name="position"/>
<xsl:choose>
<xsl:when test="contains($celldata, ',')">
<xsl:element name="{exsl:node-set($elements)//element[position() = $position]}">
<xsl:value-of select="substring-before($celldata, ',')"/>
</xsl:element>
<xsl:call-template name="cell">
<xsl:with-param name="celldata" select="substring-after($celldata, ',')"/>
<xsl:with-param name="position" select="number($position) + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{$elements//element[position() = $position]}">
<xsl:value-of select="$celldata"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
很抱歉使用此功能进行评论,但不确定如何通过评论格式化代码: 谢谢Rupesh,但如果 1)只有少数字段被选择在输出文件中, 2)字段名称可能需要在输出中更改为其他名称?
对于1),将xsl更改为以下,仅输出3个选定的字段
<xsl:variable name="elements">
<element>SubGroupName</element>
<element>ItemName</element>
<element>ItemValue</element>
</xsl:variable>
它不起作用?
对于2),让我们说,GroupValue被重命名为&#34; Field1&#34;在输出中,&#34; ItemName&#34;被重命名为&#34; Field2&#34;在输出中,这些是唯一需要的2个字段......
<?xml version="1.0" encoding="utf-8"?>
<Document>
<data>
<Field1>A</Field1>
<Field2>1</Field2>
</data>
<data>
<Field1></Field1>
<Field2>2</Field2>
</data>
<data>
<Field1>A</Field1>
<Field2>1</Field2>
</data>
</Document>
最后,输入字段可能包含空格,例如
<root>
Group Name,Group Value,Sub Group Name,Sub Group Value,Item Name,Item Value
,A,1,C,1,G
1,,1,C,2,H
1,A,2,D,1,I
</root>