我们对XML结构进行了更改,因此输入现在看起来像这样:
<EXPORT>
<DOCUMENTS>
<DOCUMENT>
<INDEX NAME="NAME" VALUE="folder"/>
<INDEX NAME="LOCATION" VALUE="C:\here"/>
</DOCUMENT>
<DOCUMENT>
<INDEX NAME="COLOR" VALUE="blue"/>
<INDEX NAME="LOCATION" VALUE="C:\here"/>
<INDEX NAME="DATE" VALUE="01-25-2015"/>
</DOCUMENT>
</DOCUMENTS>
</EXPORT>
对于此示例,我想获得以下CSV输出:
NAME,LOCATION,COLOR,DATE
folder, c:\here,,
,C:\here,blue,01-25-2015
我痛苦地尝试了很多东西,但我不知道generate-id
是如何工作的。我最终完成了不完整的XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="delimiter" select="','"/>
<xsl:key name="fields" match="/EXPORT/DOCUMENTS/*" use="./@name"/>
<xsl:variable name="Fields"
select="/EXPORT/DOCUMENTS/*[generate-id()=generate-id(key('fields', local-name())[1])]" />
<xsl:template match="/">
<xsl:for-each select="$Fields">
<xsl:value-of select="local-name()" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:apply-templates select="*/*" />
</xsl:template>
<xsl:template match="*">
<xsl:variable name="this" select="." />
<xsl:for-each select="$Fields">
<xsl:value-of select="$this/*[local-name() = local-name(current())]" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>
我应该改变什么?你有更好的方法吗?
答案 0 :(得分:3)
你的第一个问题是关键
<xsl:key name="fields" match="/EXPORT/DOCUMENTS/*" use="./@name"/>
这只是获取DOCUMENT
元素,当你真正想要INDEX
元素时。此外,它区分大小写,因此属性为@NAME
而非@name
<xsl:key name="fields" match="/EXPORT/DOCUMENTS/DOCUMENT/*" use="@NAME"/>
但是,当你使用密钥时,你正在使用local-name()
很多,但这会得到元素的名称(在这种情况下,总是INDEX
),所以你需要全部替换local-name()
的出现,而是获取NAME
属性。
例如:
<xsl:variable name="Fields"
select="/EXPORT/DOCUMENTS/DOCUMENT/*[generate-id()=generate-id(key('fields', @NAME)[1])]" />
另请注意,输出字段值时,您希望输出VALUE
属性的值,而不是元素本身的实际文本值
<xsl:value-of select="$this/*[@NAME = $name]/@VALUE" />
试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:variable name="delimiter" select="','"/>
<xsl:key name="fields" match="/EXPORT/DOCUMENTS/DOCUMENT/*" use="./@NAME"/>
<xsl:variable name="Fields"
select="/EXPORT/DOCUMENTS/DOCUMENT/*[generate-id()=generate-id(key('fields', @NAME)[1])]" />
<xsl:template match="/">
<xsl:for-each select="$Fields">
<xsl:value-of select="@NAME" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
<xsl:apply-templates select="*/*/*" />
</xsl:template>
<xsl:template match="*">
<xsl:variable name="this" select="." />
<xsl:for-each select="$Fields">
<xsl:variable name="name" select="@NAME" />
<xsl:value-of select="$this/*[@NAME = $name]/@VALUE" />
<xsl:if test="position() < last()">
<xsl:value-of select="$delimiter" />
</xsl:if>
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:template>
</xsl:stylesheet>